mirror of
https://github.com/systemd/systemd.git
synced 2024-12-22 17:35:35 +03:00
Merge pull request #17859 from keszybz/hostnamed-export-hostname-origin-and-simplify-logic
Export hostname origin and simplify logic in hostamed
This commit is contained in:
commit
ecfbbf098c
@ -1,6 +1,9 @@
|
|||||||
<?xml version='1.0'?> <!--*-nxml-*-->
|
<?xml version='1.0'?> <!--*-nxml-*-->
|
||||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
||||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
|
||||||
|
<!ENTITY % entities SYSTEM "custom-entities.ent" >
|
||||||
|
%entities;
|
||||||
|
]>
|
||||||
<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
|
<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
|
||||||
|
|
||||||
<refentry id="hostname">
|
<refentry id="hostname">
|
||||||
@ -26,23 +29,65 @@
|
|||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Description</title>
|
<title>Description</title>
|
||||||
|
|
||||||
<para>The <filename>/etc/hostname</filename> file configures the
|
<para>The <filename>/etc/hostname</filename> file configures the name of the local system. Unless
|
||||||
name of the local system that is set during boot using the
|
overridden as described in the next section,
|
||||||
<citerefentry><refentrytitle>sethostname</refentrytitle><manvolnum>2</manvolnum></citerefentry>
|
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry> will set this
|
||||||
system call. It should contain a single newline-terminated
|
hostname during boot using the
|
||||||
hostname string. Comments (lines starting with a `#') are ignored.
|
<citerefentry><refentrytitle>sethostname</refentrytitle><manvolnum>2</manvolnum></citerefentry> system
|
||||||
The hostname may be a free-form string up to 64 characters in length;
|
call.</para>
|
||||||
however, it is recommended that it consists only of 7-bit ASCII lower-case
|
|
||||||
characters and no spaces or dots, and limits itself to the format allowed
|
<para>The file should contain a single newline-terminated hostname string. Comments (lines starting with
|
||||||
for DNS domain name labels, even though this is not a strict
|
a <literal>#</literal>) are ignored. The hostname should be composed of up to 64 7-bit ASCII lower-case
|
||||||
requirement.</para>
|
alphanumeric characters or hyphens forming a valid DNS domain name. It is recommended that this name
|
||||||
|
contains only a single label, i.e. without any dots. Invalid characters will be filtered out in an
|
||||||
|
attempt to make the name valid, but obviously it is recommended to use a valid name and not rely on this
|
||||||
|
filtering.</para>
|
||||||
|
|
||||||
<para>You may use
|
<para>You may use
|
||||||
<citerefentry><refentrytitle>hostnamectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
<citerefentry><refentrytitle>hostnamectl</refentrytitle><manvolnum>1</manvolnum></citerefentry> to change
|
||||||
to change the value of this file during runtime from the command
|
the value of this file during runtime from the command line. Use
|
||||||
line. Use
|
<citerefentry><refentrytitle>systemd-firstboot</refentrytitle><manvolnum>1</manvolnum></citerefentry> to
|
||||||
<citerefentry><refentrytitle>systemd-firstboot</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
initialize it on mounted (but not booted) system images.</para>
|
||||||
to initialize it on mounted (but not booted) system images.</para>
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Hostname semantics</title>
|
||||||
|
|
||||||
|
<para><citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry> and the
|
||||||
|
associated tools will obtain the hostname in the following ways:</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem><para>If the kernel commandline parameter <varname>systemd.hostname=</varname> specifies a
|
||||||
|
valid hostname,
|
||||||
|
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry> will use it
|
||||||
|
to set the hostname during early boot, see
|
||||||
|
<citerefentry><refentrytitle>kernel-command-line</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
|
||||||
|
</para></listitem>
|
||||||
|
|
||||||
|
<listitem><para>Otherwise, the "static" hostname specified by <filename>/etc/hostname</filename> as
|
||||||
|
described above will be used.</para></listitem>
|
||||||
|
|
||||||
|
<listitem><para>Otherwise, a transient hostname may be set during runtime, for example based on
|
||||||
|
information in a DHCP lease, see
|
||||||
|
<citerefentry><refentrytitle>systemd-hostnamed.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
|
||||||
|
Both <ulink url="https://developer.gnome.org/NetworkManager/stable/">NetworkManager</ulink> and
|
||||||
|
<citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||||
|
allow this. Note that
|
||||||
|
<citerefentry><refentrytitle>systemd-hostnamed.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||||
|
gives higher priority to the static hostname, so the transient hostname will only be used if the static
|
||||||
|
hostname is not configured.</para></listitem>
|
||||||
|
|
||||||
|
<listitem><para>Otherwise, a fallback hostname configured at compilation time will be used
|
||||||
|
(<literal>&FALLBACK_HOSTNAME;</literal>).</para></listitem>
|
||||||
|
|
||||||
|
<!-- what about the "linux" fallback fallback? -->
|
||||||
|
</itemizedlist>
|
||||||
|
|
||||||
|
<para>Effectively, the static hostname has higher priority than a transient hostname, which has higher
|
||||||
|
priority than the fallback hostname. Transient hostnames are equivalent, so setting a new transient
|
||||||
|
hostname causes the previous transient hostname to be forgotten. The hostname specified on the kernel
|
||||||
|
command line is like a transient hostname, with the exception that it has higher priority when the
|
||||||
|
machine boots. Also note that those are the semantics implemented by systemd tools, but other programs
|
||||||
|
may also set the hostname.</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
|
@ -32,33 +32,23 @@
|
|||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Description</title>
|
<title>Description</title>
|
||||||
|
|
||||||
<para><command>hostnamectl</command> may be used to query and
|
<para><command>hostnamectl</command> may be used to query and change the system hostname and related
|
||||||
change the system hostname and related settings.</para>
|
settings.</para>
|
||||||
|
|
||||||
<para>This tool distinguishes three different hostnames: the
|
<para><citerefentry><refentrytitle>systemd-hostnamed.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||||
high-level "pretty" hostname which might include all kinds of
|
and this tool distinguish three different hostnames: the high-level "pretty" hostname which might include
|
||||||
special characters (e.g. "Lennart's Laptop"), the static hostname
|
all kinds of special characters (e.g. "Lennart's Laptop"), the "static" hostname which is the
|
||||||
which is used to initialize the kernel hostname at boot (e.g.
|
user-configured hostname (e.g. "lennarts-laptop"), and the transient hostname which is a fallback value
|
||||||
"lennarts-laptop"), and the transient hostname which is a fallback
|
received from network configuration (e.g. "node12345678"). If a static hostname is set to a valid value,
|
||||||
value received from network configuration. If a static hostname is
|
then the transient hostname is not used.</para>
|
||||||
set, and is valid (something other than localhost), then the
|
|
||||||
transient hostname is not used.</para>
|
|
||||||
|
|
||||||
<para>Note that the pretty hostname has little restrictions on the characters and length used, while the static and
|
<para>Note that the pretty hostname has little restrictions on the characters and length used, while the static and
|
||||||
transient hostnames are limited to the usually accepted characters of Internet domain names, and 64 characters at
|
transient hostnames are limited to the usually accepted characters of Internet domain names, and 64 characters at
|
||||||
maximum (the latter being a Linux limitation).</para>
|
maximum (the latter being a Linux limitation).</para>
|
||||||
|
|
||||||
<para>The static hostname is stored in
|
|
||||||
<filename>/etc/hostname</filename>, see
|
|
||||||
<citerefentry><refentrytitle>hostname</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
|
||||||
for more information. The pretty hostname, chassis type, and icon
|
|
||||||
name are stored in <filename>/etc/machine-info</filename>, see
|
|
||||||
<citerefentry><refentrytitle>machine-info</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
|
|
||||||
|
|
||||||
<para>Use
|
<para>Use
|
||||||
<citerefentry><refentrytitle>systemd-firstboot</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
<citerefentry><refentrytitle>systemd-firstboot</refentrytitle><manvolnum>1</manvolnum></citerefentry> to
|
||||||
to initialize the system hostname for mounted (but not booted)
|
initialize the system hostname for mounted (but not booted) system images.</para>
|
||||||
system images.</para>
|
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
|
@ -62,6 +62,9 @@ node /org/freedesktop/hostname1 {
|
|||||||
readonly s Hostname = '...';
|
readonly s Hostname = '...';
|
||||||
readonly s StaticHostname = '...';
|
readonly s StaticHostname = '...';
|
||||||
readonly s PrettyHostname = '...';
|
readonly s PrettyHostname = '...';
|
||||||
|
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||||
|
readonly s FallbackHostname = '...';
|
||||||
|
readonly s HostnameSource = '...';
|
||||||
readonly s IconName = '...';
|
readonly s IconName = '...';
|
||||||
readonly s Chassis = '...';
|
readonly s Chassis = '...';
|
||||||
readonly s Deployment = '...';
|
readonly s Deployment = '...';
|
||||||
@ -113,6 +116,10 @@ node /org/freedesktop/hostname1 {
|
|||||||
|
|
||||||
<variablelist class="dbus-property" generated="True" extra-ref="PrettyHostname"/>
|
<variablelist class="dbus-property" generated="True" extra-ref="PrettyHostname"/>
|
||||||
|
|
||||||
|
<variablelist class="dbus-property" generated="True" extra-ref="FallbackHostname"/>
|
||||||
|
|
||||||
|
<variablelist class="dbus-property" generated="True" extra-ref="HostnameSource"/>
|
||||||
|
|
||||||
<variablelist class="dbus-property" generated="True" extra-ref="IconName"/>
|
<variablelist class="dbus-property" generated="True" extra-ref="IconName"/>
|
||||||
|
|
||||||
<variablelist class="dbus-property" generated="True" extra-ref="Chassis"/>
|
<variablelist class="dbus-property" generated="True" extra-ref="Chassis"/>
|
||||||
@ -144,55 +151,61 @@ node /org/freedesktop/hostname1 {
|
|||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Semantics</title>
|
<title>Semantics</title>
|
||||||
|
|
||||||
<para>The <emphasis>static (configured) hostname</emphasis> is the one configured in
|
<para>The <varname>StaticHostname</varname> property exposes the "static" hostname configured in
|
||||||
<filename>/etc/hostname</filename>. It is chosen by the local user. It is not always in sync with the
|
<filename>/etc/hostname</filename>. It is not always in sync with the current hostname as returned by the
|
||||||
current hostname as returned by the
|
|
||||||
<citerefentry project="man-pages"><refentrytitle>gethostname</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
<citerefentry project="man-pages"><refentrytitle>gethostname</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||||
system call. If no hostname is configured this property will be the empty string. Setting this property
|
system call. If no static hostname is configured this property will be the empty string.</para>
|
||||||
to the empty string will remove <filename>/etc/hostname</filename>. This property should be an
|
|
||||||
internet-style hostname, 7-bit lowercase ASCII, no special chars/spaces.</para>
|
|
||||||
|
|
||||||
<para>The <emphasis>transient (dynamic) hostname</emphasis> is the one configured via the kernel's
|
<para>When <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry> or
|
||||||
|
<citerefentry><refentrytitle>systemd-hostnamed.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||||
|
set the hostname, this static hostname <emphasis>has the highest priority</emphasis>.</para>
|
||||||
|
|
||||||
|
<para>The <varname>Hostname</varname> property exposes the actual hostname configured in the kernel via
|
||||||
<citerefentry project="man-pages"><refentrytitle>sethostname</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
|
<citerefentry project="man-pages"><refentrytitle>sethostname</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
|
||||||
It can be different from the static hostname if DHCP or mDNS have been configured to change the name
|
It can be different from the static hostname. This property is never empty.</para>
|
||||||
based on network information. <!-- FIXME: it's not DHCP that configures this... -->
|
|
||||||
This property is never empty. If no hostname is set this will default to
|
|
||||||
<literal>&FALLBACK_HOSTNAME;</literal> (configurable at compilation time). Setting this property to the
|
|
||||||
empty string will reset the dynamic hostname to the static hostname. If no static hostname is
|
|
||||||
configured the dynamic hostname will be reset to <literal>&FALLBACK_HOSTNAME;</literal>. This property
|
|
||||||
should be an internet-style hostname, 7-bit lowercase ASCII, no special chars/spaces.</para>
|
|
||||||
|
|
||||||
<para>The <emphasis>pretty hostname</emphasis> is a free-form UTF-8 hostname for presentation to the
|
<para>The <varname>PrettyHostname</varname> property exposes the <emphasis>pretty hostname</emphasis>
|
||||||
user. User interfaces should ensure that the pretty hostname and the static hostname stay in sync.
|
which is a free-form UTF-8 hostname for presentation to the user. User interfaces should ensure that the
|
||||||
I.e. when the former is <literal>Lennart’s Computer</literal> the latter should be
|
pretty hostname and the static hostname stay in sync. E.g. when the former is <literal>Lennart’s
|
||||||
<literal>lennarts-computer</literal>. If no pretty hostname is set this setting will be the empty
|
Computer</literal> the latter should be <literal>lennarts-computer</literal>. If no pretty hostname is
|
||||||
string. Applications should then find a suitable fallback, such as the dynamic hostname.</para>
|
set this setting will be the empty string. Applications should then find a suitable fallback, such as the
|
||||||
|
dynamic hostname.</para>
|
||||||
|
|
||||||
<para>The <emphasis>icon name</emphasis> is a name following the XDG icon naming spec. If not set,
|
<para>The <varname>FallbackHostname</varname> property exposes the fallback hostname (configured at
|
||||||
information such as the chassis type (see below) is used to find a suitable fallback icon name
|
compilation time).</para>
|
||||||
(i.e. <literal>computer-laptop</literal> vs. <literal>computer-desktop</literal> is picked based on the
|
|
||||||
chassis information). If no such data is available, the empty string is returned. In that case an application
|
|
||||||
should fall back to a replacement icon, for example <literal>computer</literal>. If this property is set
|
|
||||||
to the empty string, the automatic fallback name selection is enabled again.</para>
|
|
||||||
|
|
||||||
<para>The <emphasis>chassis type</emphasis> should be one of the currently defined chassis types:
|
<para>The <varname>HostnameSource</varname> property exposes the origin of the currently configured
|
||||||
<literal>desktop</literal>, <literal>laptop</literal>, <literal>server</literal>,
|
hostname. One of <literal>static</literal> (set from <filename>/etc/hostname</filename>),
|
||||||
<literal>tablet</literal>, <literal>handset</literal>, as well as the special chassis types
|
<literal>transient</literal> (a non-permanent hostname from an external source),
|
||||||
<literal>vm</literal> and <literal>container</literal> for virtualized systems. Note that in most cases
|
<literal>fallback</literal> (the compiled-in fallback value).</para>
|
||||||
the chassis type will be determined automatically from DMI/SMBIOS/ACPI firmware information. Writing to
|
|
||||||
this setting is hence useful only to override misdetected chassis types, or to configure the chassis type if
|
<para>The <varname>IconName</varname> property exposes the <emphasis>icon name</emphasis> following the
|
||||||
it could not be auto-detected. Set this property to the empty string to reenable the automatic detection of
|
XDG icon naming spec. If not set, information such as the chassis type (see below) is used to find a
|
||||||
the chassis type from firmware information.</para>
|
suitable fallback icon name (i.e. <literal>computer-laptop</literal>
|
||||||
|
vs. <literal>computer-desktop</literal> is picked based on the chassis information). If no such data is
|
||||||
|
available, the empty string is returned. In that case an application should fall back to a replacement
|
||||||
|
icon, for example <literal>computer</literal>. If this property is set to the empty string, the automatic
|
||||||
|
fallback name selection is enabled again.</para>
|
||||||
|
|
||||||
|
<para>The <varname>Chassis</varname> property exposes a <emphasis>chassis type</emphasis>, one of the
|
||||||
|
currently defined chassis types: <literal>desktop</literal>, <literal>laptop</literal>,
|
||||||
|
<literal>server</literal>, <literal>tablet</literal>, <literal>handset</literal>, as well as the special
|
||||||
|
chassis types <literal>vm</literal> and <literal>container</literal> for virtualized systems. Note that
|
||||||
|
in most cases the chassis type will be determined automatically from DMI/SMBIOS/ACPI firmware
|
||||||
|
information. Writing to this setting is hence useful only to override misdetected chassis types, or to
|
||||||
|
configure the chassis type if it could not be auto-detected. Set this property to the empty string to
|
||||||
|
reenable the automatic detection of the chassis type from firmware information.</para>
|
||||||
|
|
||||||
<para>Note that <filename>systemd-hostnamed</filename> starts only on request and terminates after a
|
<para>Note that <filename>systemd-hostnamed</filename> starts only on request and terminates after a
|
||||||
short idle period. This effectively means that <function>PropertyChanged</function> messages are not sent
|
short idle period. This effectively means that <function>PropertyChanged</function> messages are not sent
|
||||||
out for changes made directly on the files (as in: administrator edits the files with vi). This is
|
out for changes made directly on the files (as in: administrator edits the files with vi). This is
|
||||||
the intended behavior: manual configuration changes should require manual reloading.</para>
|
the intended behavior: manual configuration changes should require manual reloading.</para>
|
||||||
|
|
||||||
<para>The transient (dynamic) hostname maps directly to the kernel hostname. This hostname should be
|
<para>The transient (dynamic) hostname exposed by the <varname>Hostname</varname> property maps directly
|
||||||
assumed to be highly dynamic, and hence should be watched directly, without depending on
|
to the kernel hostname. This hostname should be assumed to be highly dynamic, and hence should be watched
|
||||||
<function>PropertyChanged</function> messages from <filename>systemd-hostnamed</filename>. To accomplish
|
directly, without depending on <function>PropertyChanged</function> messages from
|
||||||
this, open <filename>/proc/sys/kernel/hostname</filename> and
|
<filename>systemd-hostnamed</filename>. To accomplish this, open
|
||||||
|
<filename>/proc/sys/kernel/hostname</filename> and
|
||||||
<citerefentry project="man-pages"><refentrytitle>poll</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
<citerefentry project="man-pages"><refentrytitle>poll</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||||
for <constant>SIGHUP</constant> which is triggered by the kernel every time the hostname changes. Again:
|
for <constant>SIGHUP</constant> which is triggered by the kernel every time the hostname changes. Again:
|
||||||
this is special for the transient (dynamic) hostname, and does not apply to the configured (fixed)
|
this is special for the transient (dynamic) hostname, and does not apply to the configured (fixed)
|
||||||
@ -206,15 +219,17 @@ node /org/freedesktop/hostname1 {
|
|||||||
for that. For more information on these files and syscalls see the respective man pages.</para>
|
for that. For more information on these files and syscalls see the respective man pages.</para>
|
||||||
|
|
||||||
<refsect2>
|
<refsect2>
|
||||||
<title>Methods and Properties</title>
|
<title>Methods</title>
|
||||||
|
|
||||||
<para><function>SetHostname()</function> sets the transient (dynamic) hostname which is exposed by the
|
<para><function>SetHostname()</function> sets the transient (dynamic) hostname, which is used if no
|
||||||
<varname>Hostname</varname> property. If empty, the transient hostname is set to the static hostname.
|
static hostname is set. This value must be an internet-style hostname, 7-bit lowercase ASCII, no
|
||||||
</para>
|
special chars/spaces. An empty string will unset the transient hostname.</para>
|
||||||
|
|
||||||
<para><function>SetStaticHostname()</function> sets the static hostname which is exposed by the
|
<para><function>SetStaticHostname()</function> sets the static hostname which is exposed by the
|
||||||
<varname>StaticHostname</varname> property. If empty, the built-in default of
|
<varname>StaticHostname</varname> property. When called with an empty argument, the static
|
||||||
<literal>&FALLBACK_HOSTNAME;</literal> is used.</para>
|
configuration in <filename>/etc/hostname</filename> is removed. Since the static hostname has the
|
||||||
|
highest priority, calling this function usually affects also the <varname>Hostname</varname> property
|
||||||
|
and the effective hostname configured in the kernel.</para>
|
||||||
|
|
||||||
<para><function>SetPrettyHostname()</function> sets the pretty hostname which is exposed by the
|
<para><function>SetPrettyHostname()</function> sets the pretty hostname which is exposed by the
|
||||||
<varname>PrettyHostname</varname> property.</para>
|
<varname>PrettyHostname</varname> property.</para>
|
||||||
@ -287,10 +302,6 @@ node /org/freedesktop/hostname1 {
|
|||||||
with <citerefentry><refentrytitle>nss-myhostname</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
|
with <citerefentry><refentrytitle>nss-myhostname</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>A client that wants to change the local hostname for DHCP/mDNS should invoke
|
|
||||||
<code>SetHostname("newname", false)</code> as soon as the name is available and afterwards reset it via
|
|
||||||
<code>SetHostname("")</code>.</para>
|
|
||||||
|
|
||||||
<para>Here are some recommendations to follow when generating a static (internet) hostname from a pretty
|
<para>Here are some recommendations to follow when generating a static (internet) hostname from a pretty
|
||||||
name:
|
name:
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
|
@ -51,9 +51,15 @@
|
|||||||
</listitem>
|
</listitem>
|
||||||
</itemizedlist></para>
|
</itemizedlist></para>
|
||||||
|
|
||||||
|
<para>The static hostname is stored in <filename>/etc/hostname</filename>, see
|
||||||
|
<citerefentry><refentrytitle>hostname</refentrytitle><manvolnum>5</manvolnum></citerefentry> for more
|
||||||
|
information. The pretty hostname, chassis type, and icon name are stored in
|
||||||
|
<filename>/etc/machine-info</filename>, see
|
||||||
|
<citerefentry><refentrytitle>machine-info</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
|
||||||
|
|
||||||
<para>The tool
|
<para>The tool
|
||||||
<citerefentry><refentrytitle>hostnamectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
<citerefentry><refentrytitle>hostnamectl</refentrytitle><manvolnum>1</manvolnum></citerefentry> is a
|
||||||
is a command line client to this service.</para>
|
command line client to this service.</para>
|
||||||
|
|
||||||
<para>See
|
<para>See
|
||||||
<citerefentry><refentrytitle>org.freedesktop.hostname1</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
<citerefentry><refentrytitle>org.freedesktop.hostname1</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||||
|
@ -7,28 +7,10 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
#include "fd-util.h"
|
|
||||||
#include "fileio.h"
|
|
||||||
#include "hostname-util.h"
|
#include "hostname-util.h"
|
||||||
#include "macro.h"
|
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
|
|
||||||
bool hostname_is_set(void) {
|
|
||||||
struct utsname u;
|
|
||||||
|
|
||||||
assert_se(uname(&u) >= 0);
|
|
||||||
|
|
||||||
if (isempty(u.nodename))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/* This is the built-in kernel default hostname */
|
|
||||||
if (streq(u.nodename, "(none)"))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* gethostname_malloc(void) {
|
char* gethostname_malloc(void) {
|
||||||
struct utsname u;
|
struct utsname u;
|
||||||
const char *s;
|
const char *s;
|
||||||
@ -208,105 +190,3 @@ bool is_localhost(const char *hostname) {
|
|||||||
endswith_no_case(hostname, ".localhost.localdomain") ||
|
endswith_no_case(hostname, ".localhost.localdomain") ||
|
||||||
endswith_no_case(hostname, ".localhost.localdomain.");
|
endswith_no_case(hostname, ".localhost.localdomain.");
|
||||||
}
|
}
|
||||||
|
|
||||||
int sethostname_idempotent(const char *s) {
|
|
||||||
char buf[HOST_NAME_MAX + 1] = {};
|
|
||||||
|
|
||||||
assert(s);
|
|
||||||
|
|
||||||
if (gethostname(buf, sizeof(buf)) < 0)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
if (streq(buf, s))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (sethostname(s, strlen(s)) < 0)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int shorten_overlong(const char *s, char **ret) {
|
|
||||||
char *h, *p;
|
|
||||||
|
|
||||||
/* Shorten an overlong name to HOST_NAME_MAX or to the first dot,
|
|
||||||
* whatever comes earlier. */
|
|
||||||
|
|
||||||
assert(s);
|
|
||||||
|
|
||||||
h = strdup(s);
|
|
||||||
if (!h)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
if (hostname_is_valid(h, 0)) {
|
|
||||||
*ret = h;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = strchr(h, '.');
|
|
||||||
if (p)
|
|
||||||
*p = 0;
|
|
||||||
|
|
||||||
strshorten(h, HOST_NAME_MAX);
|
|
||||||
|
|
||||||
if (!hostname_is_valid(h, 0)) {
|
|
||||||
free(h);
|
|
||||||
return -EDOM;
|
|
||||||
}
|
|
||||||
|
|
||||||
*ret = h;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int read_etc_hostname_stream(FILE *f, char **ret) {
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(f);
|
|
||||||
assert(ret);
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
_cleanup_free_ char *line = NULL;
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
r = read_line(f, LONG_LINE_MAX, &line);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
if (r == 0) /* EOF without any hostname? the file is empty, let's treat that exactly like no file at all: ENOENT */
|
|
||||||
return -ENOENT;
|
|
||||||
|
|
||||||
p = strstrip(line);
|
|
||||||
|
|
||||||
/* File may have empty lines or comments, ignore them */
|
|
||||||
if (!IN_SET(*p, '\0', '#')) {
|
|
||||||
char *copy;
|
|
||||||
|
|
||||||
hostname_cleanup(p); /* normalize the hostname */
|
|
||||||
|
|
||||||
if (!hostname_is_valid(p, VALID_HOSTNAME_TRAILING_DOT)) /* check that the hostname we return is valid */
|
|
||||||
return -EBADMSG;
|
|
||||||
|
|
||||||
copy = strdup(p);
|
|
||||||
if (!copy)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
*ret = copy;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int read_etc_hostname(const char *path, char **ret) {
|
|
||||||
_cleanup_fclose_ FILE *f = NULL;
|
|
||||||
|
|
||||||
assert(ret);
|
|
||||||
|
|
||||||
if (!path)
|
|
||||||
path = "/etc/hostname";
|
|
||||||
|
|
||||||
f = fopen(path, "re");
|
|
||||||
if (!f)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
return read_etc_hostname_stream(f, ret);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -7,8 +7,6 @@
|
|||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
|
|
||||||
bool hostname_is_set(void);
|
|
||||||
|
|
||||||
char* gethostname_malloc(void);
|
char* gethostname_malloc(void);
|
||||||
char* gethostname_short_malloc(void);
|
char* gethostname_short_malloc(void);
|
||||||
int gethostname_strict(char **ret);
|
int gethostname_strict(char **ret);
|
||||||
@ -29,10 +27,3 @@ static inline bool is_gateway_hostname(const char *hostname) {
|
|||||||
/* This tries to identify the valid syntaxes for the our synthetic "gateway" host. */
|
/* This tries to identify the valid syntaxes for the our synthetic "gateway" host. */
|
||||||
return STRCASE_IN_SET(hostname, "_gateway", "_gateway.");
|
return STRCASE_IN_SET(hostname, "_gateway", "_gateway.");
|
||||||
}
|
}
|
||||||
|
|
||||||
int sethostname_idempotent(const char *s);
|
|
||||||
|
|
||||||
int shorten_overlong(const char *s, char **ret);
|
|
||||||
|
|
||||||
int read_etc_hostname_stream(FILE *f, char **ret);
|
|
||||||
int read_etc_hostname(const char *path, char **ret);
|
|
||||||
|
@ -78,6 +78,7 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
|
|||||||
_DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope)
|
_DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope)
|
||||||
|
|
||||||
#define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,)
|
#define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,)
|
||||||
|
#define DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,)
|
||||||
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,static)
|
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,static)
|
||||||
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,static)
|
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,static)
|
||||||
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,static)
|
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,static)
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "alloc-util.h"
|
|
||||||
#include "fileio.h"
|
|
||||||
#include "hostname-setup.h"
|
|
||||||
#include "hostname-util.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "macro.h"
|
|
||||||
#include "proc-cmdline.h"
|
|
||||||
#include "string-util.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
int hostname_setup(void) {
|
|
||||||
_cleanup_free_ char *b = NULL;
|
|
||||||
const char *hn = NULL;
|
|
||||||
bool enoent = false;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
r = proc_cmdline_get_key("systemd.hostname", 0, &b);
|
|
||||||
if (r < 0)
|
|
||||||
log_warning_errno(r, "Failed to retrieve system hostname from kernel command line, ignoring: %m");
|
|
||||||
else if (r > 0) {
|
|
||||||
if (hostname_is_valid(b, VALID_HOSTNAME_TRAILING_DOT))
|
|
||||||
hn = b;
|
|
||||||
else {
|
|
||||||
log_warning("Hostname specified on kernel command line is invalid, ignoring: %s", b);
|
|
||||||
b = mfree(b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hn) {
|
|
||||||
r = read_etc_hostname(NULL, &b);
|
|
||||||
if (r == -ENOENT)
|
|
||||||
enoent = true;
|
|
||||||
else if (r < 0)
|
|
||||||
log_warning_errno(r, "Failed to read configured hostname, ignoring: %m");
|
|
||||||
else
|
|
||||||
hn = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isempty(hn)) {
|
|
||||||
/* Don't override the hostname if it is already set and not explicitly configured */
|
|
||||||
if (hostname_is_set())
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (enoent)
|
|
||||||
log_info("No hostname configured.");
|
|
||||||
|
|
||||||
hn = FALLBACK_HOSTNAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = sethostname_idempotent(hn);
|
|
||||||
if (r < 0)
|
|
||||||
return log_warning_errno(r, "Failed to set hostname to <%s>: %m", hn);
|
|
||||||
|
|
||||||
log_info("Set hostname to <%s>.", hn);
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
int hostname_setup(void);
|
|
@ -2064,7 +2064,7 @@ static int initialize_runtime(
|
|||||||
}
|
}
|
||||||
|
|
||||||
status_welcome();
|
status_welcome();
|
||||||
hostname_setup();
|
(void) hostname_setup(true);
|
||||||
/* Force transient machine-id on first boot. */
|
/* Force transient machine-id on first boot. */
|
||||||
machine_id_setup(NULL, first_boot, arg_machine_id, NULL);
|
machine_id_setup(NULL, first_boot, arg_machine_id, NULL);
|
||||||
(void) loopback_setup();
|
(void) loopback_setup();
|
||||||
|
@ -76,8 +76,6 @@ libcore_sources = '''
|
|||||||
execute.h
|
execute.h
|
||||||
generator-setup.c
|
generator-setup.c
|
||||||
generator-setup.h
|
generator-setup.h
|
||||||
hostname-setup.c
|
|
||||||
hostname-setup.h
|
|
||||||
ima-setup.c
|
ima-setup.c
|
||||||
ima-setup.h
|
ima-setup.h
|
||||||
ip-address-access.c
|
ip-address-access.c
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
#include "fuzz.h"
|
#include "fuzz.h"
|
||||||
#include "hostname-util.h"
|
#include "hostname-setup.h"
|
||||||
|
|
||||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||||
_cleanup_fclose_ FILE *f = NULL;
|
_cleanup_fclose_ FILE *f = NULL;
|
@ -123,7 +123,7 @@ fuzzers += [
|
|||||||
[libshared],
|
[libshared],
|
||||||
[]],
|
[]],
|
||||||
|
|
||||||
[['src/fuzz/fuzz-hostname-util.c'],
|
[['src/fuzz/fuzz-hostname-setup.c'],
|
||||||
[libshared],
|
[libshared],
|
||||||
[]],
|
[]],
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
#include "bus-common-errors.h"
|
#include "bus-common-errors.h"
|
||||||
|
#include "bus-get-properties.h"
|
||||||
#include "bus-log-control-api.h"
|
#include "bus-log-control-api.h"
|
||||||
#include "bus-polkit.h"
|
#include "bus-polkit.h"
|
||||||
#include "def.h"
|
#include "def.h"
|
||||||
@ -16,6 +17,7 @@
|
|||||||
#include "env-util.h"
|
#include "env-util.h"
|
||||||
#include "fileio-label.h"
|
#include "fileio-label.h"
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
|
#include "hostname-setup.h"
|
||||||
#include "hostname-util.h"
|
#include "hostname-util.h"
|
||||||
#include "id128-util.h"
|
#include "id128-util.h"
|
||||||
#include "main-func.h"
|
#include "main-func.h"
|
||||||
@ -29,6 +31,7 @@
|
|||||||
#include "service-util.h"
|
#include "service-util.h"
|
||||||
#include "signal-util.h"
|
#include "signal-util.h"
|
||||||
#include "stat-util.h"
|
#include "stat-util.h"
|
||||||
|
#include "string-table.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
#include "user-util.h"
|
#include "user-util.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
@ -58,6 +61,8 @@ enum {
|
|||||||
typedef struct Context {
|
typedef struct Context {
|
||||||
char *data[_PROP_MAX];
|
char *data[_PROP_MAX];
|
||||||
|
|
||||||
|
HostnameSource hostname_source;
|
||||||
|
|
||||||
struct stat etc_hostname_stat;
|
struct stat etc_hostname_stat;
|
||||||
struct stat etc_os_release_stat;
|
struct stat etc_os_release_stat;
|
||||||
struct stat etc_machine_info_stat;
|
struct stat etc_machine_info_stat;
|
||||||
@ -66,11 +71,9 @@ typedef struct Context {
|
|||||||
} Context;
|
} Context;
|
||||||
|
|
||||||
static void context_reset(Context *c, uint64_t mask) {
|
static void context_reset(Context *c, uint64_t mask) {
|
||||||
int p;
|
|
||||||
|
|
||||||
assert(c);
|
assert(c);
|
||||||
|
|
||||||
for (p = 0; p < _PROP_MAX; p++) {
|
for (int p = 0; p < _PROP_MAX; p++) {
|
||||||
if (!FLAGS_SET(mask, UINT64_C(1) << p))
|
if (!FLAGS_SET(mask, UINT64_C(1) << p))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -312,63 +315,63 @@ static char* context_fallback_icon_name(Context *c) {
|
|||||||
return strdup("computer");
|
return strdup("computer");
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool hostname_is_useful(const char *hn) {
|
|
||||||
return !isempty(hn) && !is_localhost(hn);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int context_update_kernel_hostname(
|
static int context_update_kernel_hostname(
|
||||||
Context *c,
|
Context *c,
|
||||||
const char *transient_hn) {
|
const char *transient_hn) {
|
||||||
|
|
||||||
const char *static_hn, *hn;
|
const char *hn;
|
||||||
struct utsname u;
|
HostnameSource hns;
|
||||||
|
int r;
|
||||||
|
|
||||||
assert(c);
|
assert(c);
|
||||||
|
|
||||||
if (!transient_hn) {
|
/* /etc/hostname has the highest preference ... */
|
||||||
/* If no transient hostname is passed in, then let's check what is currently set. */
|
if (c->data[PROP_STATIC_HOSTNAME]) {
|
||||||
assert_se(uname(&u) >= 0);
|
hn = c->data[PROP_STATIC_HOSTNAME];
|
||||||
transient_hn =
|
hns = HOSTNAME_STATIC;
|
||||||
isempty(u.nodename) || streq(u.nodename, "(none)") ? NULL : u.nodename;
|
|
||||||
}
|
|
||||||
|
|
||||||
static_hn = c->data[PROP_STATIC_HOSTNAME];
|
|
||||||
|
|
||||||
/* /etc/hostname with something other than "localhost"
|
|
||||||
* has the highest preference ... */
|
|
||||||
if (hostname_is_useful(static_hn))
|
|
||||||
hn = static_hn;
|
|
||||||
|
|
||||||
/* ... the transient hostname, (ie: DHCP) comes next ... */
|
/* ... the transient hostname, (ie: DHCP) comes next ... */
|
||||||
else if (!isempty(transient_hn))
|
} else if (transient_hn) {
|
||||||
hn = transient_hn;
|
hn = transient_hn;
|
||||||
|
hns = HOSTNAME_TRANSIENT;
|
||||||
/* ... fallback to static "localhost.*" ignored above ... */
|
|
||||||
else if (!isempty(static_hn))
|
|
||||||
hn = static_hn;
|
|
||||||
|
|
||||||
/* ... and the ultimate fallback */
|
/* ... and the ultimate fallback */
|
||||||
else
|
} else {
|
||||||
hn = FALLBACK_HOSTNAME;
|
hn = FALLBACK_HOSTNAME;
|
||||||
|
hns = HOSTNAME_FALLBACK;
|
||||||
|
}
|
||||||
|
|
||||||
if (sethostname_idempotent(hn) < 0)
|
r = sethostname_idempotent(hn);
|
||||||
return -errno;
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to set hostname: %m");
|
||||||
|
|
||||||
|
if (c->hostname_source != hns) {
|
||||||
|
c->hostname_source = hns;
|
||||||
|
r = 1;
|
||||||
|
}
|
||||||
|
|
||||||
(void) nscd_flush_cache(STRV_MAKE("hosts"));
|
(void) nscd_flush_cache(STRV_MAKE("hosts"));
|
||||||
|
|
||||||
return 0;
|
if (r == 0)
|
||||||
|
log_debug("Hostname was already set to <%s>.", hn);
|
||||||
|
else {
|
||||||
|
log_info("Hostname set to <%s> (%s)", hn, hostname_source_to_string(hns));
|
||||||
|
|
||||||
|
hostname_update_source_hint(hn, hns);
|
||||||
|
}
|
||||||
|
|
||||||
|
return r; /* 0 if no change, 1 if something was done */
|
||||||
}
|
}
|
||||||
|
|
||||||
static int context_write_data_static_hostname(Context *c) {
|
static int context_write_data_static_hostname(Context *c) {
|
||||||
assert(c);
|
assert(c);
|
||||||
|
|
||||||
if (isempty(c->data[PROP_STATIC_HOSTNAME])) {
|
if (isempty(c->data[PROP_STATIC_HOSTNAME])) {
|
||||||
|
|
||||||
if (unlink("/etc/hostname") < 0)
|
if (unlink("/etc/hostname") < 0)
|
||||||
return errno == ENOENT ? 0 : -errno;
|
return errno == ENOENT ? 0 : -errno;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return write_string_file_atomic_label("/etc/hostname", c->data[PROP_STATIC_HOSTNAME]);
|
return write_string_file_atomic_label("/etc/hostname", c->data[PROP_STATIC_HOSTNAME]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,7 +386,7 @@ static int context_write_data_machine_info(Context *c) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
_cleanup_strv_free_ char **l = NULL;
|
_cleanup_strv_free_ char **l = NULL;
|
||||||
int r, p;
|
int r;
|
||||||
|
|
||||||
assert(c);
|
assert(c);
|
||||||
|
|
||||||
@ -391,7 +394,7 @@ static int context_write_data_machine_info(Context *c) {
|
|||||||
if (r < 0 && r != -ENOENT)
|
if (r < 0 && r != -ENOENT)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
for (p = PROP_PRETTY_HOSTNAME; p <= PROP_LOCATION; p++) {
|
for (int p = PROP_PRETTY_HOSTNAME; p <= PROP_LOCATION; p++) {
|
||||||
_cleanup_free_ char *t = NULL;
|
_cleanup_free_ char *t = NULL;
|
||||||
char **u;
|
char **u;
|
||||||
|
|
||||||
@ -461,6 +464,52 @@ static int property_get_static_hostname(
|
|||||||
return sd_bus_message_append(reply, "s", c->data[PROP_STATIC_HOSTNAME]);
|
return sd_bus_message_append(reply, "s", c->data[PROP_STATIC_HOSTNAME]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_fallback_hostname, "s", FALLBACK_HOSTNAME);
|
||||||
|
|
||||||
|
static int property_get_hostname_source(
|
||||||
|
sd_bus *bus,
|
||||||
|
const char *path,
|
||||||
|
const char *interface,
|
||||||
|
const char *property,
|
||||||
|
sd_bus_message *reply,
|
||||||
|
void *userdata,
|
||||||
|
sd_bus_error *error) {
|
||||||
|
|
||||||
|
Context *c = userdata;
|
||||||
|
int r;
|
||||||
|
assert(c);
|
||||||
|
|
||||||
|
context_read_etc_hostname(c);
|
||||||
|
|
||||||
|
if (c->hostname_source < 0) {
|
||||||
|
char hostname[HOST_NAME_MAX + 1] = {};
|
||||||
|
_cleanup_free_ char *fallback = NULL;
|
||||||
|
|
||||||
|
(void) get_hostname_filtered(hostname);
|
||||||
|
|
||||||
|
if (streq_ptr(hostname, c->data[PROP_STATIC_HOSTNAME]))
|
||||||
|
c->hostname_source = HOSTNAME_STATIC;
|
||||||
|
|
||||||
|
else {
|
||||||
|
/* If the hostname was not set by us, try to figure out where it came from. If we set
|
||||||
|
* it to the fallback hostname, the file will tell us. We compare the string because
|
||||||
|
* it is possible that the hostname was set by an older version that had a different
|
||||||
|
* fallback, in the initramfs or before we reexecuted. */
|
||||||
|
|
||||||
|
r = read_one_line_file("/run/systemd/fallback-hostname", &fallback);
|
||||||
|
if (r < 0 && r != -ENOENT)
|
||||||
|
log_warning_errno(r, "Failed to read /run/systemd/fallback-hostname, ignoring: %m");
|
||||||
|
|
||||||
|
if (streq_ptr(fallback, hostname))
|
||||||
|
c->hostname_source = HOSTNAME_FALLBACK;
|
||||||
|
else
|
||||||
|
c->hostname_source = HOSTNAME_TRANSIENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sd_bus_message_append(reply, "s", hostname_source_to_string(c->hostname_source));
|
||||||
|
}
|
||||||
|
|
||||||
static int property_get_machine_info_field(
|
static int property_get_machine_info_field(
|
||||||
sd_bus *bus,
|
sd_bus *bus,
|
||||||
const char *path,
|
const char *path,
|
||||||
@ -579,7 +628,6 @@ static int method_set_hostname(sd_bus_message *m, void *userdata, sd_bus_error *
|
|||||||
Context *c = userdata;
|
Context *c = userdata;
|
||||||
const char *name;
|
const char *name;
|
||||||
int interactive, r;
|
int interactive, r;
|
||||||
struct utsname u;
|
|
||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
assert(c);
|
assert(c);
|
||||||
@ -588,20 +636,15 @@ static int method_set_hostname(sd_bus_message *m, void *userdata, sd_bus_error *
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
context_read_etc_hostname(c);
|
name = empty_to_null(name);
|
||||||
|
|
||||||
if (isempty(name))
|
/* We always go through with the procedure below without comparing to the current hostname, because
|
||||||
name = c->data[PROP_STATIC_HOSTNAME];
|
* we might want to adjust hostname source information even if the actual hostname is unchanged. */
|
||||||
|
|
||||||
if (isempty(name))
|
|
||||||
name = FALLBACK_HOSTNAME;
|
|
||||||
|
|
||||||
if (!hostname_is_valid(name, 0))
|
if (!hostname_is_valid(name, 0))
|
||||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", name);
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", name);
|
||||||
|
|
||||||
assert_se(uname(&u) >= 0);
|
context_read_etc_hostname(c);
|
||||||
if (streq_ptr(name, u.nodename))
|
|
||||||
return sd_bus_reply_method_return(m, NULL);
|
|
||||||
|
|
||||||
r = bus_verify_polkit_async(
|
r = bus_verify_polkit_async(
|
||||||
m,
|
m,
|
||||||
@ -618,14 +661,12 @@ static int method_set_hostname(sd_bus_message *m, void *userdata, sd_bus_error *
|
|||||||
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
||||||
|
|
||||||
r = context_update_kernel_hostname(c, name);
|
r = context_update_kernel_hostname(c, name);
|
||||||
if (r < 0) {
|
if (r < 0)
|
||||||
log_error_errno(r, "Failed to set hostname: %m");
|
|
||||||
return sd_bus_error_set_errnof(error, r, "Failed to set hostname: %m");
|
return sd_bus_error_set_errnof(error, r, "Failed to set hostname: %m");
|
||||||
}
|
else if (r > 0)
|
||||||
|
(void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m),
|
||||||
log_info("Changed hostname to '%s'", name);
|
"/org/freedesktop/hostname1", "org.freedesktop.hostname1",
|
||||||
|
"Hostname", "HostnameSource", NULL);
|
||||||
(void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/hostname1", "org.freedesktop.hostname1", "Hostname", NULL);
|
|
||||||
|
|
||||||
return sd_bus_reply_method_return(m, NULL);
|
return sd_bus_reply_method_return(m, NULL);
|
||||||
}
|
}
|
||||||
@ -650,7 +691,7 @@ static int method_set_static_hostname(sd_bus_message *m, void *userdata, sd_bus_
|
|||||||
if (streq_ptr(name, c->data[PROP_STATIC_HOSTNAME]))
|
if (streq_ptr(name, c->data[PROP_STATIC_HOSTNAME]))
|
||||||
return sd_bus_reply_method_return(m, NULL);
|
return sd_bus_reply_method_return(m, NULL);
|
||||||
|
|
||||||
if (!isempty(name) && !hostname_is_valid(name, 0))
|
if (name && !hostname_is_valid(name, 0))
|
||||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid static hostname '%s'", name);
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid static hostname '%s'", name);
|
||||||
|
|
||||||
r = bus_verify_polkit_async(
|
r = bus_verify_polkit_async(
|
||||||
@ -671,21 +712,21 @@ static int method_set_static_hostname(sd_bus_message *m, void *userdata, sd_bus_
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = context_update_kernel_hostname(c, NULL);
|
|
||||||
if (r < 0) {
|
|
||||||
log_error_errno(r, "Failed to set hostname: %m");
|
|
||||||
return sd_bus_error_set_errnof(error, r, "Failed to set hostname: %m");
|
|
||||||
}
|
|
||||||
|
|
||||||
r = context_write_data_static_hostname(c);
|
r = context_write_data_static_hostname(c);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_error_errno(r, "Failed to write static hostname: %m");
|
log_error_errno(r, "Failed to write static hostname: %m");
|
||||||
return sd_bus_error_set_errnof(error, r, "Failed to set static hostname: %m");
|
return sd_bus_error_set_errnof(error, r, "Failed to set static hostname: %m");
|
||||||
}
|
}
|
||||||
|
|
||||||
log_info("Changed static hostname to '%s'", strna(c->data[PROP_STATIC_HOSTNAME]));
|
r = context_update_kernel_hostname(c, NULL);
|
||||||
|
if (r < 0) {
|
||||||
|
log_error_errno(r, "Failed to set hostname: %m");
|
||||||
|
return sd_bus_error_set_errnof(error, r, "Failed to set hostname: %m");
|
||||||
|
}
|
||||||
|
|
||||||
(void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/hostname1", "org.freedesktop.hostname1", "StaticHostname", NULL);
|
(void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m),
|
||||||
|
"/org/freedesktop/hostname1", "org.freedesktop.hostname1",
|
||||||
|
"StaticHostname", "Hostname", "HostnameSource", NULL);
|
||||||
|
|
||||||
return sd_bus_reply_method_return(m, NULL);
|
return sd_bus_reply_method_return(m, NULL);
|
||||||
}
|
}
|
||||||
@ -850,6 +891,8 @@ static const sd_bus_vtable hostname_vtable[] = {
|
|||||||
SD_BUS_PROPERTY("Hostname", "s", property_get_hostname, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
SD_BUS_PROPERTY("Hostname", "s", property_get_hostname, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||||
SD_BUS_PROPERTY("StaticHostname", "s", property_get_static_hostname, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
SD_BUS_PROPERTY("StaticHostname", "s", property_get_static_hostname, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||||
SD_BUS_PROPERTY("PrettyHostname", "s", property_get_machine_info_field, offsetof(Context, data) + sizeof(char*) * PROP_PRETTY_HOSTNAME, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
SD_BUS_PROPERTY("PrettyHostname", "s", property_get_machine_info_field, offsetof(Context, data) + sizeof(char*) * PROP_PRETTY_HOSTNAME, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||||
|
SD_BUS_PROPERTY("FallbackHostname", "s", property_get_fallback_hostname, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||||
|
SD_BUS_PROPERTY("HostnameSource", "s", property_get_hostname_source, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||||
SD_BUS_PROPERTY("IconName", "s", property_get_icon_name, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
SD_BUS_PROPERTY("IconName", "s", property_get_icon_name, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||||
SD_BUS_PROPERTY("Chassis", "s", property_get_chassis, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
SD_BUS_PROPERTY("Chassis", "s", property_get_chassis, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||||
SD_BUS_PROPERTY("Deployment", "s", property_get_machine_info_field, offsetof(Context, data) + sizeof(char*) * PROP_DEPLOYMENT, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
SD_BUS_PROPERTY("Deployment", "s", property_get_machine_info_field, offsetof(Context, data) + sizeof(char*) * PROP_DEPLOYMENT, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||||
@ -960,7 +1003,9 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **ret) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int run(int argc, char *argv[]) {
|
static int run(int argc, char *argv[]) {
|
||||||
_cleanup_(context_destroy) Context context = {};
|
_cleanup_(context_destroy) Context context = {
|
||||||
|
.hostname_source = _HOSTNAME_INVALID, /* appropriate value will be set later */
|
||||||
|
};
|
||||||
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
|
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
|
||||||
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "escape.h"
|
#include "escape.h"
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
#include "dhcp-client-internal.h"
|
#include "dhcp-client-internal.h"
|
||||||
|
#include "hostname-setup.h"
|
||||||
#include "hostname-util.h"
|
#include "hostname-util.h"
|
||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
#include "network-internal.h"
|
#include "network-internal.h"
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
#include "dhcp-lease-internal.h"
|
#include "dhcp-lease-internal.h"
|
||||||
#include "ether-addr-util.h"
|
#include "ether-addr-util.h"
|
||||||
#include "hostname-util.h"
|
#include "hostname-setup.h"
|
||||||
#include "network-internal.h"
|
#include "network-internal.h"
|
||||||
#include "networkd-manager.h"
|
#include "networkd-manager.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
#include "fs-util.h"
|
#include "fs-util.h"
|
||||||
#include "gpt.h"
|
#include "gpt.h"
|
||||||
#include "hexdecoct.h"
|
#include "hexdecoct.h"
|
||||||
|
#include "hostname-setup.h"
|
||||||
#include "hostname-util.h"
|
#include "hostname-util.h"
|
||||||
#include "id128-util.h"
|
#include "id128-util.h"
|
||||||
#include "io-util.h"
|
#include "io-util.h"
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
#include "fsck-util.h"
|
#include "fsck-util.h"
|
||||||
#include "gpt.h"
|
#include "gpt.h"
|
||||||
#include "hexdecoct.h"
|
#include "hexdecoct.h"
|
||||||
#include "hostname-util.h"
|
#include "hostname-setup.h"
|
||||||
#include "id128-util.h"
|
#include "id128-util.h"
|
||||||
#include "mkdir.h"
|
#include "mkdir.h"
|
||||||
#include "mount-util.h"
|
#include "mount-util.h"
|
||||||
|
236
src/shared/hostname-setup.c
Normal file
236
src/shared/hostname-setup.c
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "alloc-util.h"
|
||||||
|
#include "fd-util.h"
|
||||||
|
#include "fileio.h"
|
||||||
|
#include "fs-util.h"
|
||||||
|
#include "hostname-setup.h"
|
||||||
|
#include "hostname-util.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "macro.h"
|
||||||
|
#include "proc-cmdline.h"
|
||||||
|
#include "string-table.h"
|
||||||
|
#include "string-util.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
static int sethostname_idempotent_full(const char *s, bool really) {
|
||||||
|
char buf[HOST_NAME_MAX + 1] = {};
|
||||||
|
|
||||||
|
assert(s);
|
||||||
|
|
||||||
|
if (gethostname(buf, sizeof(buf) - 1) < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
if (streq(buf, s))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (really &&
|
||||||
|
sethostname(s, strlen(s)) < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sethostname_idempotent(const char *s) {
|
||||||
|
return sethostname_idempotent_full(s, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get_hostname_filtered(char ret[static HOST_NAME_MAX + 1]) {
|
||||||
|
char buf[HOST_NAME_MAX + 1] = {};
|
||||||
|
|
||||||
|
/* Returns true if we got a good hostname, false otherwise. */
|
||||||
|
|
||||||
|
if (gethostname(buf, sizeof(buf) - 1) < 0)
|
||||||
|
return false; /* This can realistically only fail with ENAMETOOLONG.
|
||||||
|
* Let's treat that case the same as an invalid hostname. */
|
||||||
|
|
||||||
|
if (isempty(buf))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* This is the built-in kernel default hostname */
|
||||||
|
if (streq(buf, "(none)"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
memcpy(ret, buf, sizeof buf);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int shorten_overlong(const char *s, char **ret) {
|
||||||
|
char *h, *p;
|
||||||
|
|
||||||
|
/* Shorten an overlong name to HOST_NAME_MAX or to the first dot,
|
||||||
|
* whatever comes earlier. */
|
||||||
|
|
||||||
|
assert(s);
|
||||||
|
|
||||||
|
h = strdup(s);
|
||||||
|
if (!h)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (hostname_is_valid(h, 0)) {
|
||||||
|
*ret = h;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = strchr(h, '.');
|
||||||
|
if (p)
|
||||||
|
*p = 0;
|
||||||
|
|
||||||
|
strshorten(h, HOST_NAME_MAX);
|
||||||
|
|
||||||
|
if (!hostname_is_valid(h, 0)) {
|
||||||
|
free(h);
|
||||||
|
return -EDOM;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ret = h;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_etc_hostname_stream(FILE *f, char **ret) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(f);
|
||||||
|
assert(ret);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
_cleanup_free_ char *line = NULL;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
r = read_line(f, LONG_LINE_MAX, &line);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
if (r == 0) /* EOF without any hostname? the file is empty, let's treat that exactly like no file at all: ENOENT */
|
||||||
|
return -ENOENT;
|
||||||
|
|
||||||
|
p = strstrip(line);
|
||||||
|
|
||||||
|
/* File may have empty lines or comments, ignore them */
|
||||||
|
if (!IN_SET(*p, '\0', '#')) {
|
||||||
|
char *copy;
|
||||||
|
|
||||||
|
hostname_cleanup(p); /* normalize the hostname */
|
||||||
|
|
||||||
|
if (!hostname_is_valid(p, VALID_HOSTNAME_TRAILING_DOT)) /* check that the hostname we return is valid */
|
||||||
|
return -EBADMSG;
|
||||||
|
|
||||||
|
copy = strdup(p);
|
||||||
|
if (!copy)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
*ret = copy;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_etc_hostname(const char *path, char **ret) {
|
||||||
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
|
|
||||||
|
assert(ret);
|
||||||
|
|
||||||
|
if (!path)
|
||||||
|
path = "/etc/hostname";
|
||||||
|
|
||||||
|
f = fopen(path, "re");
|
||||||
|
if (!f)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
return read_etc_hostname_stream(f, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hostname_update_source_hint(const char *hostname, HostnameSource source) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
/* Why save the value and not just create a flag file? This way we will
|
||||||
|
* notice if somebody sets the hostname directly (not going through hostnamed).
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (source == HOSTNAME_FALLBACK) {
|
||||||
|
r = write_string_file("/run/systemd/fallback-hostname", hostname,
|
||||||
|
WRITE_STRING_FILE_CREATE | WRITE_STRING_FILE_ATOMIC);
|
||||||
|
if (r < 0)
|
||||||
|
log_warning_errno(r, "Failed to create \"/run/systemd/fallback-hostname\": %m");
|
||||||
|
} else
|
||||||
|
unlink_or_warn("/run/systemd/fallback-hostname");
|
||||||
|
}
|
||||||
|
|
||||||
|
int hostname_setup(bool really) {
|
||||||
|
_cleanup_free_ char *b = NULL;
|
||||||
|
const char *hn = NULL;
|
||||||
|
HostnameSource source;
|
||||||
|
bool enoent = false;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = proc_cmdline_get_key("systemd.hostname", 0, &b);
|
||||||
|
if (r < 0)
|
||||||
|
log_warning_errno(r, "Failed to retrieve system hostname from kernel command line, ignoring: %m");
|
||||||
|
else if (r > 0) {
|
||||||
|
if (hostname_is_valid(b, true)) {
|
||||||
|
hn = b;
|
||||||
|
source = HOSTNAME_TRANSIENT;
|
||||||
|
} else {
|
||||||
|
log_warning("Hostname specified on kernel command line is invalid, ignoring: %s", b);
|
||||||
|
b = mfree(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hn) {
|
||||||
|
r = read_etc_hostname(NULL, &b);
|
||||||
|
if (r < 0) {
|
||||||
|
if (r == -ENOENT)
|
||||||
|
enoent = true;
|
||||||
|
else
|
||||||
|
log_warning_errno(r, "Failed to read configured hostname: %m");
|
||||||
|
} else {
|
||||||
|
hn = b;
|
||||||
|
source = HOSTNAME_STATIC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isempty(hn)) {
|
||||||
|
/* Don't override the hostname if it is already set and not explicitly configured */
|
||||||
|
|
||||||
|
char buf[HOST_NAME_MAX + 1] = {};
|
||||||
|
if (get_hostname_filtered(buf)) {
|
||||||
|
log_debug("No hostname configured, leaving existing hostname <%s> in place.", buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enoent)
|
||||||
|
log_info("No hostname configured, using fallback hostname.");
|
||||||
|
|
||||||
|
hn = FALLBACK_HOSTNAME;
|
||||||
|
source = HOSTNAME_FALLBACK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sethostname_idempotent_full(hn, really);
|
||||||
|
if (r < 0)
|
||||||
|
return log_warning_errno(r, "Failed to set hostname to <%s>: %m", hn);
|
||||||
|
if (r == 0)
|
||||||
|
log_debug("Hostname was already set to <%s>.", hn);
|
||||||
|
else
|
||||||
|
log_info("Hostname %s to <%s>.",
|
||||||
|
really ? "set" : "would have been set",
|
||||||
|
hn);
|
||||||
|
|
||||||
|
if (really)
|
||||||
|
hostname_update_source_hint(hn, source);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* const hostname_source_table[] = {
|
||||||
|
[HOSTNAME_STATIC] = "static",
|
||||||
|
[HOSTNAME_TRANSIENT] = "transient",
|
||||||
|
[HOSTNAME_FALLBACK] = "fallback",
|
||||||
|
};
|
||||||
|
|
||||||
|
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(hostname_source, HostnameSource);
|
24
src/shared/hostname-setup.h
Normal file
24
src/shared/hostname-setup.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
typedef enum HostnameSource {
|
||||||
|
HOSTNAME_STATIC, /* from /etc/hostname */
|
||||||
|
HOSTNAME_TRANSIENT, /* a transient hostname set through systemd, hostnamed, the container manager, or otherwise */
|
||||||
|
HOSTNAME_FALLBACK, /* the compiled-in fallback was used */
|
||||||
|
_HOSTNAME_INVALID = -1,
|
||||||
|
} HostnameSource;
|
||||||
|
|
||||||
|
const char* hostname_source_to_string(HostnameSource source);
|
||||||
|
int sethostname_idempotent(const char *s);
|
||||||
|
|
||||||
|
int shorten_overlong(const char *s, char **ret);
|
||||||
|
|
||||||
|
int read_etc_hostname_stream(FILE *f, char **ret);
|
||||||
|
int read_etc_hostname(const char *path, char **ret);
|
||||||
|
|
||||||
|
bool get_hostname_filtered(char ret[static HOST_NAME_MAX + 1]);
|
||||||
|
void hostname_update_source_hint(const char *hostname, HostnameSource source);
|
||||||
|
int hostname_setup(bool really);
|
@ -22,7 +22,7 @@
|
|||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "fs-util.h"
|
#include "fs-util.h"
|
||||||
#include "hashmap.h"
|
#include "hashmap.h"
|
||||||
#include "hostname-util.h"
|
#include "hostname-setup.h"
|
||||||
#include "id128-util.h"
|
#include "id128-util.h"
|
||||||
#include "lockfile-util.h"
|
#include "lockfile-util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
@ -115,6 +115,8 @@ shared_sources = files('''
|
|||||||
gpt.h
|
gpt.h
|
||||||
group-record.c
|
group-record.c
|
||||||
group-record.h
|
group-record.h
|
||||||
|
hostname-setup.c
|
||||||
|
hostname-setup.h
|
||||||
id128-print.c
|
id128-print.c
|
||||||
id128-print.h
|
id128-print.h
|
||||||
idn-util.c
|
idn-util.c
|
||||||
|
@ -105,17 +105,6 @@ tests += [
|
|||||||
libmount,
|
libmount,
|
||||||
libblkid]],
|
libblkid]],
|
||||||
|
|
||||||
[['src/test/test-hostname.c'],
|
|
||||||
[libcore,
|
|
||||||
libshared],
|
|
||||||
[threads,
|
|
||||||
librt,
|
|
||||||
libseccomp,
|
|
||||||
libselinux,
|
|
||||||
libmount,
|
|
||||||
libblkid],
|
|
||||||
'', 'unsafe'],
|
|
||||||
|
|
||||||
[['src/test/test-dns-domain.c'],
|
[['src/test/test-dns-domain.c'],
|
||||||
[libcore,
|
[libcore,
|
||||||
libshared],
|
libshared],
|
||||||
@ -339,6 +328,10 @@ tests += [
|
|||||||
[],
|
[],
|
||||||
[]],
|
[]],
|
||||||
|
|
||||||
|
[['src/test/test-hostname-setup.c'],
|
||||||
|
[],
|
||||||
|
[]],
|
||||||
|
|
||||||
[['src/test/test-hostname-util.c'],
|
[['src/test/test-hostname-util.c'],
|
||||||
[],
|
[],
|
||||||
[]],
|
[]],
|
||||||
|
72
src/test/test-hostname-setup.c
Normal file
72
src/test/test-hostname-setup.c
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "alloc-util.h"
|
||||||
|
#include "fileio.h"
|
||||||
|
#include "hostname-setup.h"
|
||||||
|
#include "string-util.h"
|
||||||
|
#include "tests.h"
|
||||||
|
#include "tmpfile-util.h"
|
||||||
|
|
||||||
|
static void test_read_etc_hostname(void) {
|
||||||
|
char path[] = "/tmp/hostname.XXXXXX";
|
||||||
|
char *hostname;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = mkostemp_safe(path);
|
||||||
|
assert(fd > 0);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
/* simple hostname */
|
||||||
|
assert_se(write_string_file(path, "foo", WRITE_STRING_FILE_CREATE) == 0);
|
||||||
|
assert_se(read_etc_hostname(path, &hostname) == 0);
|
||||||
|
assert_se(streq(hostname, "foo"));
|
||||||
|
hostname = mfree(hostname);
|
||||||
|
|
||||||
|
/* with comment */
|
||||||
|
assert_se(write_string_file(path, "# comment\nfoo", WRITE_STRING_FILE_CREATE) == 0);
|
||||||
|
assert_se(read_etc_hostname(path, &hostname) == 0);
|
||||||
|
assert_se(hostname);
|
||||||
|
assert_se(streq(hostname, "foo"));
|
||||||
|
hostname = mfree(hostname);
|
||||||
|
|
||||||
|
/* with comment and extra whitespace */
|
||||||
|
assert_se(write_string_file(path, "# comment\n\n foo ", WRITE_STRING_FILE_CREATE) == 0);
|
||||||
|
assert_se(read_etc_hostname(path, &hostname) == 0);
|
||||||
|
assert_se(hostname);
|
||||||
|
assert_se(streq(hostname, "foo"));
|
||||||
|
hostname = mfree(hostname);
|
||||||
|
|
||||||
|
/* cleans up name */
|
||||||
|
assert_se(write_string_file(path, "!foo/bar.com", WRITE_STRING_FILE_CREATE) == 0);
|
||||||
|
assert_se(read_etc_hostname(path, &hostname) == 0);
|
||||||
|
assert_se(hostname);
|
||||||
|
assert_se(streq(hostname, "foobar.com"));
|
||||||
|
hostname = mfree(hostname);
|
||||||
|
|
||||||
|
/* no value set */
|
||||||
|
hostname = (char*) 0x1234;
|
||||||
|
assert_se(write_string_file(path, "# nothing here\n", WRITE_STRING_FILE_CREATE) == 0);
|
||||||
|
assert_se(read_etc_hostname(path, &hostname) == -ENOENT);
|
||||||
|
assert_se(hostname == (char*) 0x1234); /* does not touch argument on error */
|
||||||
|
|
||||||
|
/* nonexisting file */
|
||||||
|
assert_se(read_etc_hostname("/non/existing", &hostname) == -ENOENT);
|
||||||
|
assert_se(hostname == (char*) 0x1234); /* does not touch argument on error */
|
||||||
|
|
||||||
|
unlink(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_hostname_setup(void) {
|
||||||
|
hostname_setup(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
test_setup_logging(LOG_DEBUG);
|
||||||
|
|
||||||
|
test_read_etc_hostname();
|
||||||
|
test_hostname_setup();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -6,8 +6,8 @@
|
|||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
#include "hostname-util.h"
|
#include "hostname-util.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
|
#include "tests.h"
|
||||||
#include "tmpfile-util.h"
|
#include "tmpfile-util.h"
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
static void test_hostname_is_valid(void) {
|
static void test_hostname_is_valid(void) {
|
||||||
assert_se(hostname_is_valid("foobar", 0));
|
assert_se(hostname_is_valid("foobar", 0));
|
||||||
@ -91,55 +91,6 @@ static void test_hostname_cleanup(void) {
|
|||||||
assert_se(streq(hostname_cleanup(s), "xxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"));
|
assert_se(streq(hostname_cleanup(s), "xxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_read_etc_hostname(void) {
|
|
||||||
char path[] = "/tmp/hostname.XXXXXX";
|
|
||||||
char *hostname;
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
fd = mkostemp_safe(path);
|
|
||||||
assert(fd > 0);
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
/* simple hostname */
|
|
||||||
assert_se(write_string_file(path, "foo", WRITE_STRING_FILE_CREATE) == 0);
|
|
||||||
assert_se(read_etc_hostname(path, &hostname) == 0);
|
|
||||||
assert_se(streq(hostname, "foo"));
|
|
||||||
hostname = mfree(hostname);
|
|
||||||
|
|
||||||
/* with comment */
|
|
||||||
assert_se(write_string_file(path, "# comment\nfoo", WRITE_STRING_FILE_CREATE) == 0);
|
|
||||||
assert_se(read_etc_hostname(path, &hostname) == 0);
|
|
||||||
assert_se(hostname);
|
|
||||||
assert_se(streq(hostname, "foo"));
|
|
||||||
hostname = mfree(hostname);
|
|
||||||
|
|
||||||
/* with comment and extra whitespace */
|
|
||||||
assert_se(write_string_file(path, "# comment\n\n foo ", WRITE_STRING_FILE_CREATE) == 0);
|
|
||||||
assert_se(read_etc_hostname(path, &hostname) == 0);
|
|
||||||
assert_se(hostname);
|
|
||||||
assert_se(streq(hostname, "foo"));
|
|
||||||
hostname = mfree(hostname);
|
|
||||||
|
|
||||||
/* cleans up name */
|
|
||||||
assert_se(write_string_file(path, "!foo/bar.com", WRITE_STRING_FILE_CREATE) == 0);
|
|
||||||
assert_se(read_etc_hostname(path, &hostname) == 0);
|
|
||||||
assert_se(hostname);
|
|
||||||
assert_se(streq(hostname, "foobar.com"));
|
|
||||||
hostname = mfree(hostname);
|
|
||||||
|
|
||||||
/* no value set */
|
|
||||||
hostname = (char*) 0x1234;
|
|
||||||
assert_se(write_string_file(path, "# nothing here\n", WRITE_STRING_FILE_CREATE) == 0);
|
|
||||||
assert_se(read_etc_hostname(path, &hostname) == -ENOENT);
|
|
||||||
assert_se(hostname == (char*) 0x1234); /* does not touch argument on error */
|
|
||||||
|
|
||||||
/* nonexisting file */
|
|
||||||
assert_se(read_etc_hostname("/non/existing", &hostname) == -ENOENT);
|
|
||||||
assert_se(hostname == (char*) 0x1234); /* does not touch argument on error */
|
|
||||||
|
|
||||||
unlink(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_hostname_malloc(void) {
|
static void test_hostname_malloc(void) {
|
||||||
_cleanup_free_ char *h = NULL, *l = NULL;
|
_cleanup_free_ char *h = NULL, *l = NULL;
|
||||||
|
|
||||||
@ -158,12 +109,10 @@ static void test_fallback_hostname(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
log_parse_environment();
|
test_setup_logging(LOG_INFO);
|
||||||
log_open();
|
|
||||||
|
|
||||||
test_hostname_is_valid();
|
test_hostname_is_valid();
|
||||||
test_hostname_cleanup();
|
test_hostname_cleanup();
|
||||||
test_read_etc_hostname();
|
|
||||||
test_hostname_malloc();
|
test_hostname_malloc();
|
||||||
|
|
||||||
test_fallback_hostname();
|
test_fallback_hostname();
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
||||||
|
|
||||||
#include "hostname-setup.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
|
||||||
int r;
|
|
||||||
|
|
||||||
r = hostname_setup();
|
|
||||||
if (r < 0)
|
|
||||||
log_error_errno(r, "hostname: %m");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -32,7 +32,7 @@ ProtectKernelLogs=yes
|
|||||||
ProtectKernelModules=yes
|
ProtectKernelModules=yes
|
||||||
ProtectKernelTunables=yes
|
ProtectKernelTunables=yes
|
||||||
ProtectSystem=strict
|
ProtectSystem=strict
|
||||||
ReadWritePaths=/etc
|
ReadWritePaths=/etc /run/systemd
|
||||||
RestrictAddressFamilies=AF_UNIX
|
RestrictAddressFamilies=AF_UNIX
|
||||||
RestrictNamespaces=yes
|
RestrictNamespaces=yes
|
||||||
RestrictRealtime=yes
|
RestrictRealtime=yes
|
||||||
|
Loading…
Reference in New Issue
Block a user