mirror of
https://github.com/systemd/systemd
synced 2026-03-05 20:54:45 +01:00
Compare commits
25 Commits
b17f651a17
...
937e305e93
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
937e305e93 | ||
|
|
43b49470d1 | ||
|
|
94b78105c6 | ||
|
|
6fe2a70b91 | ||
|
|
3a23834d6b | ||
|
|
1ecb46724c | ||
|
|
cedfd142de | ||
|
|
ba4a31b7a6 | ||
|
|
1b630835df | ||
|
|
1ca37419b1 | ||
|
|
f8ecc2c00d | ||
|
|
79485fc27a | ||
|
|
d4e9809465 | ||
|
|
52ef5dd798 | ||
|
|
9e815cf2c2 | ||
|
|
1feb8eee2d | ||
|
|
c4dd2d7575 | ||
|
|
68a3d91538 | ||
|
|
b226c15cfb | ||
|
|
f3808b872f | ||
|
|
c24288d21e | ||
|
|
b0d7d8063c | ||
|
|
3d75a443ee | ||
|
|
0c3c59783b | ||
|
|
f3bd46c657 |
@ -24,6 +24,7 @@
|
||||
<refname>sd_bus_open_with_description</refname>
|
||||
<refname>sd_bus_open_user</refname>
|
||||
<refname>sd_bus_open_user_with_description</refname>
|
||||
<refname>sd_bus_open_user_machine</refname>
|
||||
<refname>sd_bus_open_system</refname>
|
||||
<refname>sd_bus_open_system_with_description</refname>
|
||||
<refname>sd_bus_open_system_remote</refname>
|
||||
@ -73,6 +74,12 @@
|
||||
<paramdef>const char *<parameter>description</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_bus_open_user_machine</function></funcdef>
|
||||
<paramdef>sd_bus **<parameter>bus</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>machine</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_bus_open_system</function></funcdef>
|
||||
<paramdef>sd_bus **<parameter>bus</parameter></paramdef>
|
||||
@ -187,14 +194,24 @@
|
||||
work for the root user on the remote machine.</para>
|
||||
|
||||
<para><function>sd_bus_open_system_machine()</function> connects to the system bus in the specified
|
||||
<parameter>machine</parameter>, where <parameter>machine</parameter> is the name of a local
|
||||
container. See
|
||||
<parameter>machine</parameter>, where <parameter>machine</parameter> is the name of a local container,
|
||||
possibly prefixed by a user name and a separating <literal>@</literal>. If the container name is
|
||||
specified as the special string <literal>.host</literal> the connection is made to the local system. This
|
||||
is useful to connect to the local system bus as specific user, e.g. <literal>foobar@.host</literal> to
|
||||
connect to the local system bus as local user <literal>foobar</literal>. If the <literal>@</literal>
|
||||
syntax is used either the left-hand side or the right-hand side may be ommited (but not both) in which
|
||||
case the local user name or <literal>.host</literal> is implied. If the <literal>@</literal> syntax is
|
||||
not used the connection is always made as root user. See
|
||||
<citerefentry><refentrytitle>sd_bus_set_address</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
for a description of the address syntax, and
|
||||
<citerefentry><refentrytitle>machinectl</refentrytitle><manvolnum>1</manvolnum></citerefentry> for more
|
||||
information about the "machine" concept. Note that connections into local containers are only available
|
||||
to privileged processes at this time.</para>
|
||||
|
||||
<para><function>sd_bus_open_user_machine()</function> is similar to
|
||||
<function>sd_bus_open_system_machine()</function>, but connects to the user bus of the root user, or if
|
||||
the <literal>@</literal> syntax is used, of the specified user.</para>
|
||||
|
||||
<para>These calls allocate a bus connection object and initiate
|
||||
the connection to a well-known bus of some form. An alternative to
|
||||
using these high-level calls is to create an unconnected bus
|
||||
@ -210,6 +227,7 @@
|
||||
<title>Reference ownership</title>
|
||||
<para>The functions <function>sd_bus_open()</function>,
|
||||
<function>sd_bus_open_user()</function>,
|
||||
<function>sd_bus_open_user_machine()</function>,
|
||||
<function>sd_bus_open_system()</function>,
|
||||
<function>sd_bus_open_system_remote()</function>, and
|
||||
<function>sd_bus_open_system_machine()</function> return a new
|
||||
|
||||
@ -171,20 +171,27 @@
|
||||
<para> For example, disabling ARP is useful when creating multiple MACVLAN or VLAN virtual
|
||||
interfaces atop a single lower-level physical interface, which will then only serve as a
|
||||
link/"bridge" device aggregating traffic to the same physical link and not participate in
|
||||
the network otherwise.</para>
|
||||
the network otherwise. Defaults to unset.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>Multicast=</varname></term>
|
||||
<listitem>
|
||||
<para>Takes a boolean. If set to true, the multicast flag on the device is enabled.</para>
|
||||
<para>Takes a boolean. If set to true, the multicast flag on the device is enabled. Defaults to unset.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>AllMulticast=</varname></term>
|
||||
<listitem>
|
||||
<para>Takes a boolean. If set to true, the driver retrieves all multicast packets from the network.
|
||||
This happens when multicast routing is enabled.</para>
|
||||
This happens when multicast routing is enabled. Defaults to unset.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>Promiscuous=</varname></term>
|
||||
<listitem>
|
||||
<para>Takes a boolean. If set to true, promiscuous mode of the interface is enabled.
|
||||
Defaults to unset.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
|
||||
@ -45,8 +45,14 @@
|
||||
<term><option>--machine=</option></term>
|
||||
|
||||
<listitem id='machine-text'>
|
||||
<para>Execute operation on a local container. Specify a
|
||||
container name to connect to.</para>
|
||||
<para>Execute operation on a local container. Specify a container name to connect to, optionally
|
||||
prefixed by a user name to connect as and a separating <literal>@</literal> character. If the special
|
||||
string <literal>.host</literal> is used in place of the container name, a connection to the local
|
||||
system is made (which is useful to connect to a specific user's user bus: <literal>--user
|
||||
--machine=lennart@.host</literal>). If the <literal>@</literal> syntax is not used, the connection is
|
||||
made as root user. If the <literal>@</literal> syntax is used either the left hand side or the right hand
|
||||
side may be ommitted (but not both) in which case the local user name and <literal>.host</literal> are
|
||||
implied.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
@ -89,6 +89,8 @@ int gethostname_strict(char **ret) {
|
||||
}
|
||||
|
||||
bool valid_ldh_char(char c) {
|
||||
/* "LDH" → "Letters, digits, hyphens", as per RFC 5890, Section 2.3.1 */
|
||||
|
||||
return
|
||||
(c >= 'a' && c <= 'z') ||
|
||||
(c >= 'A' && c <= 'Z') ||
|
||||
@ -96,28 +98,24 @@ bool valid_ldh_char(char c) {
|
||||
c == '-';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if s looks like a valid hostname or FQDN. This does not do
|
||||
* full DNS validation, but only checks if the name is composed of
|
||||
* allowed characters and the length is not above the maximum allowed
|
||||
* by Linux (c.f. dns_name_is_valid()). Trailing dot is allowed if
|
||||
* allow_trailing_dot is true and at least two components are present
|
||||
* in the name. Note that due to the restricted charset and length
|
||||
* this call is substantially more conservative than
|
||||
* dns_name_is_valid().
|
||||
*/
|
||||
bool hostname_is_valid(const char *s, bool allow_trailing_dot) {
|
||||
bool hostname_is_valid(const char *s, ValidHostnameFlags flags) {
|
||||
unsigned n_dots = 0;
|
||||
const char *p;
|
||||
bool dot, hyphen;
|
||||
|
||||
/* Check if s looks like a valid hostname or FQDN. This does not do full DNS validation, but only
|
||||
* checks if the name is composed of allowed characters and the length is not above the maximum
|
||||
* allowed by Linux (c.f. dns_name_is_valid()). A trailing dot is allowed if
|
||||
* VALID_HOSTNAME_TRAILING_DOT flag is set and at least two components are present in the name. Note
|
||||
* that due to the restricted charset and length this call is substantially more conservative than
|
||||
* dns_name_is_valid(). Doesn't accept empty hostnames, hostnames with leading dots, and hostnames
|
||||
* with multiple dots in a sequence. Doesn't allow hyphens at the beginning or end of label. */
|
||||
|
||||
if (isempty(s))
|
||||
return false;
|
||||
|
||||
/* Doesn't accept empty hostnames, hostnames with
|
||||
* leading dots, and hostnames with multiple dots in a
|
||||
* sequence. Also ensures that the length stays below
|
||||
* HOST_NAME_MAX. */
|
||||
if (streq(s, ".host")) /* Used by the container logic to denote the "root container" */
|
||||
return FLAGS_SET(flags, VALID_HOSTNAME_DOT_HOST);
|
||||
|
||||
for (p = s, dot = hyphen = true; *p; p++)
|
||||
if (*p == '.') {
|
||||
@ -143,14 +141,13 @@ bool hostname_is_valid(const char *s, bool allow_trailing_dot) {
|
||||
hyphen = false;
|
||||
}
|
||||
|
||||
if (dot && (n_dots < 2 || !allow_trailing_dot))
|
||||
if (dot && (n_dots < 2 || !FLAGS_SET(flags, VALID_HOSTNAME_TRAILING_DOT)))
|
||||
return false;
|
||||
if (hyphen)
|
||||
return false;
|
||||
|
||||
if (p-s > HOST_NAME_MAX) /* Note that HOST_NAME_MAX is 64 on
|
||||
* Linux, but DNS allows domain names
|
||||
* up to 255 characters */
|
||||
if (p-s > HOST_NAME_MAX) /* Note that HOST_NAME_MAX is 64 on Linux, but DNS allows domain names up to
|
||||
* 255 characters */
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -241,7 +238,7 @@ int shorten_overlong(const char *s, char **ret) {
|
||||
if (!h)
|
||||
return -ENOMEM;
|
||||
|
||||
if (hostname_is_valid(h, false)) {
|
||||
if (hostname_is_valid(h, 0)) {
|
||||
*ret = h;
|
||||
return 0;
|
||||
}
|
||||
@ -252,7 +249,7 @@ int shorten_overlong(const char *s, char **ret) {
|
||||
|
||||
strshorten(h, HOST_NAME_MAX);
|
||||
|
||||
if (!hostname_is_valid(h, false)) {
|
||||
if (!hostname_is_valid(h, 0)) {
|
||||
free(h);
|
||||
return -EDOM;
|
||||
}
|
||||
@ -285,7 +282,7 @@ int read_etc_hostname_stream(FILE *f, char **ret) {
|
||||
|
||||
hostname_cleanup(p); /* normalize the hostname */
|
||||
|
||||
if (!hostname_is_valid(p, true)) /* check that the hostname we return is valid */
|
||||
if (!hostname_is_valid(p, VALID_HOSTNAME_TRAILING_DOT)) /* check that the hostname we return is valid */
|
||||
return -EBADMSG;
|
||||
|
||||
copy = strdup(p);
|
||||
|
||||
@ -14,10 +14,14 @@ char* gethostname_short_malloc(void);
|
||||
int gethostname_strict(char **ret);
|
||||
|
||||
bool valid_ldh_char(char c) _const_;
|
||||
bool hostname_is_valid(const char *s, bool allow_trailing_dot) _pure_;
|
||||
char* hostname_cleanup(char *s);
|
||||
|
||||
#define machine_name_is_valid(s) hostname_is_valid(s, false)
|
||||
typedef enum ValidHostnameFlags {
|
||||
VALID_HOSTNAME_TRAILING_DOT = 1 << 0, /* Accept trailing dot on multi-label names */
|
||||
VALID_HOSTNAME_DOT_HOST = 1 << 1, /* Accept ".host" as valid hostname */
|
||||
} ValidHostnameFlags;
|
||||
|
||||
bool hostname_is_valid(const char *s, ValidHostnameFlags flags) _pure_;
|
||||
char* hostname_cleanup(char *s);
|
||||
|
||||
bool is_localhost(const char *hostname);
|
||||
|
||||
|
||||
@ -165,7 +165,7 @@ int container_get_leader(const char *machine, pid_t *pid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!machine_name_is_valid(machine))
|
||||
if (!hostname_is_valid(machine, 0))
|
||||
return -EINVAL;
|
||||
|
||||
p = strjoina("/run/systemd/machines/", machine);
|
||||
|
||||
@ -121,7 +121,7 @@ static int acquire_bus(bool set_monitor, sd_bus **ret) {
|
||||
break;
|
||||
|
||||
case BUS_TRANSPORT_MACHINE:
|
||||
r = bus_set_address_system_machine(bus, arg_host);
|
||||
r = bus_set_address_machine(bus, arg_user, arg_host);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1194,6 +1194,7 @@ static int message_json(sd_bus_message *m, FILE *f) {
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *w = NULL;
|
||||
char e[2];
|
||||
int r;
|
||||
usec_t ts;
|
||||
|
||||
r = json_transform_message(m, &v);
|
||||
if (r < 0)
|
||||
@ -1202,6 +1203,10 @@ static int message_json(sd_bus_message *m, FILE *f) {
|
||||
e[0] = m->header->endian;
|
||||
e[1] = 0;
|
||||
|
||||
ts = m->realtime;
|
||||
if (ts == 0)
|
||||
ts = now(CLOCK_REALTIME);
|
||||
|
||||
r = json_build(&w, JSON_BUILD_OBJECT(
|
||||
JSON_BUILD_PAIR("type", JSON_BUILD_STRING(bus_message_type_to_string(m->header->type))),
|
||||
JSON_BUILD_PAIR("endian", JSON_BUILD_STRING(e)),
|
||||
@ -1209,6 +1214,7 @@ static int message_json(sd_bus_message *m, FILE *f) {
|
||||
JSON_BUILD_PAIR("version", JSON_BUILD_INTEGER(m->header->version)),
|
||||
JSON_BUILD_PAIR("cookie", JSON_BUILD_INTEGER(BUS_MESSAGE_COOKIE(m))),
|
||||
JSON_BUILD_PAIR_CONDITION(m->reply_cookie != 0, "reply_cookie", JSON_BUILD_INTEGER(m->reply_cookie)),
|
||||
JSON_BUILD_PAIR("timestamp-realtime", JSON_BUILD_UNSIGNED(ts)),
|
||||
JSON_BUILD_PAIR_CONDITION(m->sender, "sender", JSON_BUILD_STRING(m->sender)),
|
||||
JSON_BUILD_PAIR_CONDITION(m->destination, "destination", JSON_BUILD_STRING(m->destination)),
|
||||
JSON_BUILD_PAIR_CONDITION(m->path, "path", JSON_BUILD_STRING(m->path)),
|
||||
|
||||
@ -24,7 +24,7 @@ int hostname_setup(void) {
|
||||
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))
|
||||
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);
|
||||
@ -34,12 +34,11 @@ int hostname_setup(void) {
|
||||
|
||||
if (!hn) {
|
||||
r = read_etc_hostname(NULL, &b);
|
||||
if (r < 0) {
|
||||
if (r == -ENOENT)
|
||||
enoent = true;
|
||||
else if (r < 0)
|
||||
log_warning_errno(r, "Failed to read configured hostname, ignoring: %m");
|
||||
else
|
||||
log_warning_errno(r, "Failed to read configured hostname: %m");
|
||||
} else
|
||||
hn = b;
|
||||
}
|
||||
|
||||
|
||||
@ -493,7 +493,7 @@ static int prompt_hostname(void) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!hostname_is_valid(h, true)) {
|
||||
if (!hostname_is_valid(h, VALID_HOSTNAME_TRAILING_DOT)) {
|
||||
log_error("Specified hostname invalid.");
|
||||
continue;
|
||||
}
|
||||
@ -1135,15 +1135,15 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case ARG_HOSTNAME:
|
||||
if (!hostname_is_valid(optarg, true))
|
||||
if (!hostname_is_valid(optarg, VALID_HOSTNAME_TRAILING_DOT))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Host name %s is not valid.", optarg);
|
||||
|
||||
hostname_cleanup(optarg);
|
||||
r = free_and_strdup(&arg_hostname, optarg);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
hostname_cleanup(arg_hostname);
|
||||
break;
|
||||
|
||||
case ARG_MACHINE_ID:
|
||||
|
||||
@ -248,7 +248,7 @@ static int set_hostname(int argc, char **argv, void *userdata) {
|
||||
/* If the passed hostname is already valid, then assume the user doesn't know anything about pretty
|
||||
* hostnames, so let's unset the pretty hostname, and just set the passed hostname as static/dynamic
|
||||
* hostname. */
|
||||
if (arg_static && hostname_is_valid(hostname, true))
|
||||
if (arg_static && hostname_is_valid(hostname, VALID_HOSTNAME_TRAILING_DOT))
|
||||
p = ""; /* No pretty hostname (as it is redundant), just a static one */
|
||||
else
|
||||
p = hostname; /* Use the passed name as pretty hostname */
|
||||
|
||||
@ -596,7 +596,7 @@ static int method_set_hostname(sd_bus_message *m, void *userdata, sd_bus_error *
|
||||
if (isempty(name))
|
||||
name = FALLBACK_HOSTNAME;
|
||||
|
||||
if (!hostname_is_valid(name, false))
|
||||
if (!hostname_is_valid(name, 0))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", name);
|
||||
|
||||
assert_se(uname(&u) >= 0);
|
||||
@ -650,7 +650,7 @@ static int method_set_static_hostname(sd_bus_message *m, void *userdata, sd_bus_
|
||||
if (streq_ptr(name, c->data[PROP_STATIC_HOSTNAME]))
|
||||
return sd_bus_reply_method_return(m, NULL);
|
||||
|
||||
if (!isempty(name) && !hostname_is_valid(name, false))
|
||||
if (!isempty(name) && !hostname_is_valid(name, 0))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid static hostname '%s'", name);
|
||||
|
||||
r = bus_verify_polkit_async(
|
||||
|
||||
@ -65,7 +65,7 @@ static int export_tar(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_close_ int open_fd = -1;
|
||||
int r, fd;
|
||||
|
||||
if (machine_name_is_valid(argv[1])) {
|
||||
if (hostname_is_valid(argv[1], 0)) {
|
||||
r = image_find(IMAGE_MACHINE, argv[1], &image);
|
||||
if (r == -ENOENT)
|
||||
return log_error_errno(r, "Machine image %s not found.", argv[1]);
|
||||
@ -141,7 +141,7 @@ static int export_raw(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_close_ int open_fd = -1;
|
||||
int r, fd;
|
||||
|
||||
if (machine_name_is_valid(argv[1])) {
|
||||
if (hostname_is_valid(argv[1], 0)) {
|
||||
r = image_find(IMAGE_MACHINE, argv[1], &image);
|
||||
if (r == -ENOENT)
|
||||
return log_error_errno(r, "Machine image %s not found.", argv[1]);
|
||||
|
||||
@ -126,7 +126,7 @@ static int import_fs(int argc, char *argv[], void *userdata) {
|
||||
local = empty_or_dash_to_null(local);
|
||||
|
||||
if (local) {
|
||||
if (!machine_name_is_valid(local))
|
||||
if (!hostname_is_valid(local, 0))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Local image name '%s' is not valid.",
|
||||
local);
|
||||
|
||||
@ -393,7 +393,7 @@ int raw_import_start(RawImport *i, int fd, const char *local, bool force_local,
|
||||
assert(fd >= 0);
|
||||
assert(local);
|
||||
|
||||
if (!machine_name_is_valid(local))
|
||||
if (!hostname_is_valid(local, 0))
|
||||
return -EINVAL;
|
||||
|
||||
if (i->input_fd >= 0)
|
||||
|
||||
@ -329,7 +329,7 @@ int tar_import_start(TarImport *i, int fd, const char *local, bool force_local,
|
||||
assert(fd >= 0);
|
||||
assert(local);
|
||||
|
||||
if (!machine_name_is_valid(local))
|
||||
if (!hostname_is_valid(local, 0))
|
||||
return -EINVAL;
|
||||
|
||||
if (i->input_fd >= 0)
|
||||
|
||||
@ -64,7 +64,7 @@ static int import_tar(int argc, char *argv[], void *userdata) {
|
||||
|
||||
local = ll;
|
||||
|
||||
if (!machine_name_is_valid(local))
|
||||
if (!hostname_is_valid(local, 0))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Local image name '%s' is not valid.",
|
||||
local);
|
||||
@ -159,7 +159,7 @@ static int import_raw(int argc, char *argv[], void *userdata) {
|
||||
|
||||
local = ll;
|
||||
|
||||
if (!machine_name_is_valid(local))
|
||||
if (!hostname_is_valid(local, 0))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Local image name '%s' is not valid.",
|
||||
local);
|
||||
|
||||
@ -717,7 +717,7 @@ static int method_import_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_
|
||||
if (!S_ISREG(st.st_mode) && !S_ISFIFO(st.st_mode))
|
||||
return -EINVAL;
|
||||
|
||||
if (!machine_name_is_valid(local))
|
||||
if (!hostname_is_valid(local, 0))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
|
||||
"Local name %s is invalid", local);
|
||||
|
||||
@ -787,7 +787,7 @@ static int method_import_fs(sd_bus_message *msg, void *userdata, sd_bus_error *e
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!machine_name_is_valid(local))
|
||||
if (!hostname_is_valid(local, 0))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
|
||||
"Local name %s is invalid", local);
|
||||
|
||||
@ -852,7 +852,7 @@ static int method_export_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!machine_name_is_valid(local))
|
||||
if (!hostname_is_valid(local, 0))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
|
||||
"Local name %s is invalid", local);
|
||||
|
||||
@ -932,7 +932,7 @@ static int method_pull_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_er
|
||||
|
||||
if (isempty(local))
|
||||
local = NULL;
|
||||
else if (!machine_name_is_valid(local))
|
||||
else if (!hostname_is_valid(local, 0))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
|
||||
"Local name %s is invalid", local);
|
||||
|
||||
|
||||
@ -651,7 +651,7 @@ int raw_pull_start(
|
||||
if (!http_url_is_valid(url))
|
||||
return -EINVAL;
|
||||
|
||||
if (local && !machine_name_is_valid(local))
|
||||
if (local && !hostname_is_valid(local, 0))
|
||||
return -EINVAL;
|
||||
|
||||
if (i->raw_job)
|
||||
|
||||
@ -481,7 +481,7 @@ int tar_pull_start(
|
||||
if (!http_url_is_valid(url))
|
||||
return -EINVAL;
|
||||
|
||||
if (local && !machine_name_is_valid(local))
|
||||
if (local && !hostname_is_valid(local, 0))
|
||||
return -EINVAL;
|
||||
|
||||
if (i->tar_job)
|
||||
|
||||
@ -72,7 +72,7 @@ static int pull_tar(int argc, char *argv[], void *userdata) {
|
||||
|
||||
local = ll;
|
||||
|
||||
if (!machine_name_is_valid(local))
|
||||
if (!hostname_is_valid(local, 0))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Local image name '%s' is not valid.",
|
||||
local);
|
||||
@ -158,7 +158,7 @@ static int pull_raw(int argc, char *argv[], void *userdata) {
|
||||
|
||||
local = ll;
|
||||
|
||||
if (!machine_name_is_valid(local))
|
||||
if (!hostname_is_valid(local, 0))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Local image name '%s' is not valid.",
|
||||
local);
|
||||
|
||||
@ -1984,7 +1984,7 @@ _public_ int sd_journal_open_container(sd_journal **ret, const char *machine, in
|
||||
assert_return(machine, -EINVAL);
|
||||
assert_return(ret, -EINVAL);
|
||||
assert_return((flags & ~OPEN_CONTAINER_ALLOWED_FLAGS) == 0, -EINVAL);
|
||||
assert_return(machine_name_is_valid(machine), -EINVAL);
|
||||
assert_return(hostname_is_valid(machine, 0), -EINVAL);
|
||||
|
||||
p = strjoina("/run/systemd/machines/", machine);
|
||||
r = parse_env_file(NULL, p,
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
#include "sort-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "time-util.h"
|
||||
#include "utf8.h"
|
||||
#include "web-util.h"
|
||||
|
||||
@ -98,6 +99,9 @@ struct sd_dhcp_client {
|
||||
uint32_t fallback_lease_lifetime;
|
||||
uint32_t xid;
|
||||
usec_t start_time;
|
||||
usec_t t1_time;
|
||||
usec_t t2_time;
|
||||
usec_t expire_time;
|
||||
uint64_t attempt;
|
||||
uint64_t max_attempts;
|
||||
OrderedHashmap *extra_options;
|
||||
@ -540,7 +544,7 @@ int sd_dhcp_client_set_hostname(
|
||||
|
||||
/* Make sure hostnames qualify as DNS and as Linux hostnames */
|
||||
if (hostname &&
|
||||
!(hostname_is_valid(hostname, false) && dns_name_is_valid(hostname) > 0))
|
||||
!(hostname_is_valid(hostname, 0) && dns_name_is_valid(hostname) > 0))
|
||||
return -EINVAL;
|
||||
|
||||
return free_and_strdup(&client->hostname, hostname);
|
||||
@ -727,6 +731,37 @@ static void client_stop(sd_dhcp_client *client, int error) {
|
||||
client_initialize(client);
|
||||
}
|
||||
|
||||
/* RFC2131 section 4.1:
|
||||
* retransmission delays should include -1 to +1 sec of random 'fuzz'. */
|
||||
#define RFC2131_RANDOM_FUZZ \
|
||||
((int64_t)(random_u64() % (2 * USEC_PER_SEC)) - (int64_t)USEC_PER_SEC)
|
||||
|
||||
/* RFC2131 section 4.1:
|
||||
* for retransmission delays, timeout should start at 4s then double
|
||||
* each attempt with max of 64s, with -1 to +1 sec of random 'fuzz' added.
|
||||
* This assumes the first call will be using attempt 1. */
|
||||
static usec_t client_compute_request_timeout(usec_t now, uint64_t attempt) {
|
||||
usec_t timeout = (UINT64_C(1) << MIN(attempt + 1, UINT64_C(6))) * USEC_PER_SEC;
|
||||
|
||||
return usec_sub_signed(usec_add(now, timeout), RFC2131_RANDOM_FUZZ);
|
||||
}
|
||||
|
||||
/* RFC2131 section 4.4.5:
|
||||
* T1 defaults to (0.5 * duration_of_lease).
|
||||
* T2 defaults to (0.875 * duration_of_lease). */
|
||||
#define T1_DEFAULT(lifetime) ((lifetime) / 2)
|
||||
#define T2_DEFAULT(lifetime) (((lifetime) * 7) / 8)
|
||||
|
||||
/* RFC2131 section 4.4.5:
|
||||
* the client SHOULD wait one-half of the remaining time until T2 (in RENEWING state)
|
||||
* and one-half of the remaining lease time (in REBINDING state), down to a minimum
|
||||
* of 60 seconds.
|
||||
* Note that while the default T1/T2 initial times do have random 'fuzz' applied,
|
||||
* the RFC sec 4.4.5 does not mention adding any fuzz to retries. */
|
||||
static usec_t client_compute_reacquisition_timeout(usec_t now, usec_t expire) {
|
||||
return MAX(usec_sub_unsigned(expire, now) / 2, 60 * USEC_PER_SEC);
|
||||
}
|
||||
|
||||
static int cmp_uint8(const uint8_t *a, const uint8_t *b) {
|
||||
return CMP(*a, *b);
|
||||
}
|
||||
@ -1192,7 +1227,6 @@ static int client_timeout_resend(
|
||||
DHCP_CLIENT_DONT_DESTROY(client);
|
||||
usec_t next_timeout;
|
||||
uint64_t time_now;
|
||||
uint32_t time_left;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
@ -1206,19 +1240,11 @@ static int client_timeout_resend(
|
||||
switch (client->state) {
|
||||
|
||||
case DHCP_STATE_RENEWING:
|
||||
time_left = (client->lease->t2 - client->lease->t1) / 2;
|
||||
if (time_left < 60)
|
||||
time_left = 60;
|
||||
|
||||
next_timeout = time_now + time_left * USEC_PER_SEC;
|
||||
next_timeout = client_compute_reacquisition_timeout(time_now, client->t2_time);
|
||||
break;
|
||||
|
||||
case DHCP_STATE_REBINDING:
|
||||
time_left = (client->lease->lifetime - client->lease->t2) / 2;
|
||||
if (time_left < 60)
|
||||
time_left = 60;
|
||||
|
||||
next_timeout = time_now + time_left * USEC_PER_SEC;
|
||||
next_timeout = client_compute_reacquisition_timeout(time_now, client->expire_time);
|
||||
break;
|
||||
|
||||
case DHCP_STATE_REBOOTING:
|
||||
@ -1243,7 +1269,7 @@ static int client_timeout_resend(
|
||||
goto error;
|
||||
|
||||
client->attempt++;
|
||||
next_timeout = time_now + ((UINT64_C(1) << MIN(client->attempt, (uint64_t) 6)) - 1) * USEC_PER_SEC;
|
||||
next_timeout = client_compute_request_timeout(time_now, client->attempt);
|
||||
break;
|
||||
|
||||
case DHCP_STATE_STOPPED:
|
||||
@ -1251,8 +1277,6 @@ static int client_timeout_resend(
|
||||
goto error;
|
||||
}
|
||||
|
||||
next_timeout += (random_u32() & 0x1fffff);
|
||||
|
||||
r = event_reset_time(client->event, &client->timeout_resend,
|
||||
clock_boottime_or_monotonic(),
|
||||
next_timeout, 10 * USEC_PER_MSEC,
|
||||
@ -1618,25 +1642,8 @@ static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack, size_t le
|
||||
return r;
|
||||
}
|
||||
|
||||
static uint64_t client_compute_timeout(sd_dhcp_client *client, uint32_t lifetime, double factor) {
|
||||
assert(client);
|
||||
assert(client->request_sent);
|
||||
assert(lifetime > 0);
|
||||
|
||||
if (lifetime > 3)
|
||||
lifetime -= 3;
|
||||
else
|
||||
lifetime = 0;
|
||||
|
||||
return client->request_sent + (lifetime * USEC_PER_SEC * factor) +
|
||||
+ (random_u32() & 0x1fffff);
|
||||
}
|
||||
|
||||
static int client_set_lease_timeouts(sd_dhcp_client *client) {
|
||||
usec_t time_now;
|
||||
uint64_t lifetime_timeout;
|
||||
uint64_t t2_timeout;
|
||||
uint64_t t1_timeout;
|
||||
char time_string[FORMAT_TIMESPAN_MAX];
|
||||
int r;
|
||||
|
||||
@ -1659,93 +1666,76 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {
|
||||
return r;
|
||||
assert(client->request_sent <= time_now);
|
||||
|
||||
/* convert the various timeouts from relative (secs) to absolute (usecs) */
|
||||
lifetime_timeout = client_compute_timeout(client, client->lease->lifetime, 1);
|
||||
if (client->lease->t1 > 0 && client->lease->t2 > 0) {
|
||||
/* both T1 and T2 are given */
|
||||
if (client->lease->t1 < client->lease->t2 &&
|
||||
client->lease->t2 < client->lease->lifetime) {
|
||||
/* they are both valid */
|
||||
t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
|
||||
t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
|
||||
} else {
|
||||
/* discard both */
|
||||
t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
|
||||
client->lease->t2 = (client->lease->lifetime * 7) / 8;
|
||||
t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
|
||||
client->lease->t1 = client->lease->lifetime / 2;
|
||||
}
|
||||
} else if (client->lease->t2 > 0 && client->lease->t2 < client->lease->lifetime) {
|
||||
/* only T2 is given, and it is valid */
|
||||
t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
|
||||
t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
|
||||
client->lease->t1 = client->lease->lifetime / 2;
|
||||
if (t2_timeout <= t1_timeout) {
|
||||
/* the computed T1 would be invalid, so discard T2 */
|
||||
t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
|
||||
client->lease->t2 = (client->lease->lifetime * 7) / 8;
|
||||
}
|
||||
} else if (client->lease->t1 > 0 && client->lease->t1 < client->lease->lifetime) {
|
||||
/* only T1 is given, and it is valid */
|
||||
t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
|
||||
t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
|
||||
client->lease->t2 = (client->lease->lifetime * 7) / 8;
|
||||
if (t2_timeout <= t1_timeout) {
|
||||
/* the computed T2 would be invalid, so discard T1 */
|
||||
t2_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
|
||||
client->lease->t2 = client->lease->lifetime / 2;
|
||||
}
|
||||
} else {
|
||||
/* fall back to the default timeouts */
|
||||
t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
|
||||
client->lease->t1 = client->lease->lifetime / 2;
|
||||
t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
|
||||
client->lease->t2 = (client->lease->lifetime * 7) / 8;
|
||||
}
|
||||
/* verify that 0 < t2 < lifetime */
|
||||
if (client->lease->t2 == 0 || client->lease->t2 >= client->lease->lifetime)
|
||||
client->lease->t2 = T2_DEFAULT(client->lease->lifetime);
|
||||
/* verify that 0 < t1 < lifetime */
|
||||
if (client->lease->t1 == 0 || client->lease->t1 >= client->lease->t2)
|
||||
client->lease->t1 = T1_DEFAULT(client->lease->lifetime);
|
||||
/* now, if t1 >= t2, t1 *must* be T1_DEFAULT, since the previous check
|
||||
* could not evalate to false if t1 >= t2; so setting t2 to T2_DEFAULT
|
||||
* guarantees t1 < t2. */
|
||||
if (client->lease->t1 >= client->lease->t2)
|
||||
client->lease->t2 = T2_DEFAULT(client->lease->lifetime);
|
||||
|
||||
client->expire_time = client->request_sent + client->lease->lifetime * USEC_PER_SEC;
|
||||
client->t1_time = client->request_sent + client->lease->t1 * USEC_PER_SEC;
|
||||
client->t2_time = client->request_sent + client->lease->t2 * USEC_PER_SEC;
|
||||
|
||||
/* RFC2131 section 4.4.5:
|
||||
* Times T1 and T2 SHOULD be chosen with some random "fuzz".
|
||||
* Since the RFC doesn't specify here the exact 'fuzz' to use,
|
||||
* we use the range from section 4.1: -1 to +1 sec. */
|
||||
client->t1_time = usec_sub_signed(client->t1_time, RFC2131_RANDOM_FUZZ);
|
||||
client->t2_time = usec_sub_signed(client->t2_time, RFC2131_RANDOM_FUZZ);
|
||||
|
||||
/* after fuzzing, ensure t2 is still >= t1 */
|
||||
client->t2_time = MAX(client->t1_time, client->t2_time);
|
||||
|
||||
/* arm lifetime timeout */
|
||||
r = event_reset_time(client->event, &client->timeout_expire,
|
||||
clock_boottime_or_monotonic(),
|
||||
lifetime_timeout, 10 * USEC_PER_MSEC,
|
||||
client->expire_time, 10 * USEC_PER_MSEC,
|
||||
client_timeout_expire, client,
|
||||
client->event_priority, "dhcp4-lifetime", true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
log_dhcp_client(client, "lease expires in %s",
|
||||
format_timespan(time_string, FORMAT_TIMESPAN_MAX, lifetime_timeout - time_now, USEC_PER_SEC));
|
||||
|
||||
/* don't arm earlier timeouts if this has already expired */
|
||||
if (lifetime_timeout <= time_now)
|
||||
if (client->expire_time <= time_now)
|
||||
return 0;
|
||||
|
||||
log_dhcp_client(client, "lease expires in %s",
|
||||
format_timespan(time_string, FORMAT_TIMESPAN_MAX, client->expire_time - time_now, USEC_PER_SEC));
|
||||
|
||||
/* arm T2 timeout */
|
||||
r = event_reset_time(client->event, &client->timeout_t2,
|
||||
clock_boottime_or_monotonic(),
|
||||
t2_timeout, 10 * USEC_PER_MSEC,
|
||||
client->t2_time, 10 * USEC_PER_MSEC,
|
||||
client_timeout_t2, client,
|
||||
client->event_priority, "dhcp4-t2-timeout", true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
log_dhcp_client(client, "T2 expires in %s",
|
||||
format_timespan(time_string, FORMAT_TIMESPAN_MAX, t2_timeout - time_now, USEC_PER_SEC));
|
||||
|
||||
/* don't arm earlier timeout if this has already expired */
|
||||
if (t2_timeout <= time_now)
|
||||
if (client->t2_time <= time_now)
|
||||
return 0;
|
||||
|
||||
log_dhcp_client(client, "T2 expires in %s",
|
||||
format_timespan(time_string, FORMAT_TIMESPAN_MAX, client->t2_time - time_now, USEC_PER_SEC));
|
||||
|
||||
/* arm T1 timeout */
|
||||
r = event_reset_time(client->event, &client->timeout_t1,
|
||||
clock_boottime_or_monotonic(),
|
||||
t1_timeout, 10 * USEC_PER_MSEC,
|
||||
client->t1_time, 10 * USEC_PER_MSEC,
|
||||
client_timeout_t1, client,
|
||||
client->event_priority, "dhcp4-t1-timer", true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (client->t1_time > time_now)
|
||||
log_dhcp_client(client, "T1 expires in %s",
|
||||
format_timespan(time_string, FORMAT_TIMESPAN_MAX, t1_timeout - time_now, USEC_PER_SEC));
|
||||
format_timespan(time_string, FORMAT_TIMESPAN_MAX, client->t1_time - time_now, USEC_PER_SEC));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -407,7 +407,7 @@ int sd_dhcp6_client_set_fqdn(
|
||||
|
||||
/* Make sure FQDN qualifies as DNS and as Linux hostname */
|
||||
if (fqdn &&
|
||||
!(hostname_is_valid(fqdn, false) && dns_name_is_valid(fqdn) > 0))
|
||||
!(hostname_is_valid(fqdn, 0) && dns_name_is_valid(fqdn) > 0))
|
||||
return -EINVAL;
|
||||
|
||||
return free_and_strdup(&client->fqdn, fqdn);
|
||||
|
||||
@ -739,6 +739,8 @@ global:
|
||||
|
||||
LIBSYSTEMD_248 {
|
||||
global:
|
||||
sd_bus_open_user_machine;
|
||||
|
||||
sd_event_source_set_ratelimit;
|
||||
sd_event_source_get_ratelimit;
|
||||
sd_event_source_is_ratelimited;
|
||||
|
||||
@ -49,7 +49,7 @@ int bus_container_connect_socket(sd_bus *b) {
|
||||
|
||||
bus_socket_setup(b);
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
|
||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, pair) < 0)
|
||||
return -errno;
|
||||
|
||||
r = namespace_fork("(sd-buscntrns)", "(sd-buscntr)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG,
|
||||
|
||||
@ -713,7 +713,7 @@ _public_ int sd_bus_get_name_creds(
|
||||
}
|
||||
|
||||
r = bus_creds_add_more(c, mask, pid, 0);
|
||||
if (r < 0)
|
||||
if (r < 0 && r != -ESRCH) /* Return the error, but ignore ESRCH which just means the process is already gone */
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -788,7 +788,7 @@ _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **r
|
||||
}
|
||||
|
||||
r = bus_creds_add_more(c, mask, pid, 0);
|
||||
if (r < 0)
|
||||
if (r < 0 && r != -ESRCH) /* If the process vanished, then don't complain, just return what we got */
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(c);
|
||||
|
||||
@ -603,13 +603,15 @@ _public_ int sd_bus_set_property(
|
||||
return r;
|
||||
}
|
||||
|
||||
_public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_bus_creds **creds) {
|
||||
_public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_bus_creds **ret) {
|
||||
sd_bus_creds *c;
|
||||
int r;
|
||||
|
||||
assert_return(call, -EINVAL);
|
||||
assert_return(call->sealed, -EPERM);
|
||||
assert_return(call->bus, -EINVAL);
|
||||
assert_return(!bus_pid_changed(call->bus), -ECHILD);
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
if (!BUS_IS_OPEN(call->bus->state))
|
||||
return -ENOTCONN;
|
||||
@ -618,7 +620,7 @@ _public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_b
|
||||
|
||||
/* All data we need? */
|
||||
if (c && (mask & ~c->mask) == 0) {
|
||||
*creds = sd_bus_creds_ref(c);
|
||||
*ret = sd_bus_creds_ref(c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -629,15 +631,22 @@ _public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_b
|
||||
|
||||
if (call->sender)
|
||||
/* There's a sender, but the creds are missing. */
|
||||
return sd_bus_get_name_creds(call->bus, call->sender, mask, creds);
|
||||
return sd_bus_get_name_creds(call->bus, call->sender, mask, ret);
|
||||
else
|
||||
/* There's no sender. For direct connections
|
||||
* the credentials of the AF_UNIX peer matter,
|
||||
* which may be queried via sd_bus_get_owner_creds(). */
|
||||
return sd_bus_get_owner_creds(call->bus, mask, creds);
|
||||
return sd_bus_get_owner_creds(call->bus, mask, ret);
|
||||
}
|
||||
|
||||
return bus_creds_extend_by_pid(c, mask, creds);
|
||||
r = bus_creds_extend_by_pid(c, mask, ret);
|
||||
if (r == -ESRCH) {
|
||||
/* Process doesn't exist anymore? propagate the few things we have */
|
||||
*ret = sd_bus_creds_ref(c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
_public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability) {
|
||||
|
||||
@ -55,6 +55,15 @@ _public_ int sd_bus_message_dump(sd_bus_message *m, FILE *f, uint64_t flags) {
|
||||
f = stdout;
|
||||
|
||||
if (flags & SD_BUS_MESSAGE_DUMP_WITH_HEADER) {
|
||||
char buf[FORMAT_TIMESTAMP_MAX];
|
||||
const char *p;
|
||||
usec_t ts = m->realtime;
|
||||
|
||||
if (ts == 0)
|
||||
ts = now(CLOCK_REALTIME);
|
||||
|
||||
p = format_timestamp_style(buf, sizeof(buf), ts, TIMESTAMP_US_UTC);
|
||||
|
||||
fprintf(f,
|
||||
"%s%s%s Type=%s%s%s Endian=%c Flags=%u Version=%u",
|
||||
m->header->type == SD_BUS_MESSAGE_METHOD_ERROR ? ansi_highlight_red() :
|
||||
@ -81,6 +90,8 @@ _public_ int sd_bus_message_dump(sd_bus_message *m, FILE *f, uint64_t flags) {
|
||||
if (m->reply_cookie != 0)
|
||||
fprintf(f, " ReplyCookie=%" PRIu64, m->reply_cookie);
|
||||
|
||||
fprintf(f, " Timestamp=\"%s\"", strna(p));
|
||||
|
||||
fputs("\n", f);
|
||||
|
||||
if (m->sender)
|
||||
|
||||
@ -401,7 +401,7 @@ void bus_close_io_fds(sd_bus *b);
|
||||
int bus_set_address_system(sd_bus *bus);
|
||||
int bus_set_address_user(sd_bus *bus);
|
||||
int bus_set_address_system_remote(sd_bus *b, const char *host);
|
||||
int bus_set_address_system_machine(sd_bus *b, const char *machine);
|
||||
int bus_set_address_machine(sd_bus *b, bool user, const char *machine);
|
||||
|
||||
int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error);
|
||||
|
||||
|
||||
@ -41,6 +41,7 @@
|
||||
#include "process-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "user-util.h"
|
||||
|
||||
#define log_debug_bus_message(m) \
|
||||
do { \
|
||||
@ -973,7 +974,7 @@ static int parse_container_unix_address(sd_bus *b, const char **p, char **guid)
|
||||
return -EINVAL;
|
||||
|
||||
if (machine) {
|
||||
if (!streq(machine, ".host") && !machine_name_is_valid(machine))
|
||||
if (!hostname_is_valid(machine, VALID_HOSTNAME_DOT_HOST))
|
||||
return -EINVAL;
|
||||
|
||||
free_and_replace(b->machine, machine);
|
||||
@ -1448,7 +1449,7 @@ int bus_set_address_system_remote(sd_bus *b, const char *host) {
|
||||
}
|
||||
|
||||
if (!in_charset(p, "0123456789") || *p == '\0') {
|
||||
if (!machine_name_is_valid(p) || got_forward_slash)
|
||||
if (!hostname_is_valid(p, 0) || got_forward_slash)
|
||||
return -EINVAL;
|
||||
|
||||
m = TAKE_PTR(p);
|
||||
@ -1463,7 +1464,7 @@ int bus_set_address_system_remote(sd_bus *b, const char *host) {
|
||||
interpret_port_as_machine_old_syntax:
|
||||
/* Let's make sure this is not a port of some kind,
|
||||
* and is a valid machine name. */
|
||||
if (!in_charset(m, "0123456789") && machine_name_is_valid(m))
|
||||
if (!in_charset(m, "0123456789") && hostname_is_valid(m, 0))
|
||||
c = strjoina(",argv", p ? "7" : "5", "=--machine=", m);
|
||||
}
|
||||
|
||||
@ -1514,13 +1515,90 @@ _public_ int sd_bus_open_system_remote(sd_bus **ret, const char *host) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bus_set_address_system_machine(sd_bus *b, const char *machine) {
|
||||
_cleanup_free_ char *e = NULL;
|
||||
int bus_set_address_machine(sd_bus *b, bool user, const char *machine) {
|
||||
const char *rhs;
|
||||
char *a;
|
||||
|
||||
assert(b);
|
||||
assert(machine);
|
||||
|
||||
rhs = strchr(machine, '@');
|
||||
if (rhs || user) {
|
||||
_cleanup_free_ char *u = NULL, *eu = NULL, *erhs = NULL;
|
||||
|
||||
/* If there's an "@" in the container specification, we'll connect as a user specified at its
|
||||
* left hand side, which is useful in combination with user=true. This isn't as trivial as it
|
||||
* might sound: it's not sufficient to enter the container and connect to some socket there,
|
||||
* since the --user socket path depends on $XDG_RUNTIME_DIR which is set via PAM. Thus, to be
|
||||
* able to connect, we need to have a PAM session. Our way out? We use systemd-run to get
|
||||
* into the container and acquire a PAM session there, and then invoke systemd-stdio-bridge
|
||||
* in it, which propagates the bus transport to us.*/
|
||||
|
||||
if (rhs) {
|
||||
if (rhs > machine)
|
||||
u = strndup(machine, rhs - machine);
|
||||
else
|
||||
u = getusername_malloc(); /* Empty user name, let's use the local one */
|
||||
if (!u)
|
||||
return -ENOMEM;
|
||||
|
||||
eu = bus_address_escape(u);
|
||||
if (!eu)
|
||||
return -ENOMEM;
|
||||
|
||||
rhs++;
|
||||
} else {
|
||||
/* No "@" specified but we shall connect to the user instance? Then assume root (and
|
||||
* not a user named identically to the calling one). This means:
|
||||
*
|
||||
* --machine=foobar --user → connect to user bus of root user in container "foobar"
|
||||
* --machine=@foobar --user → connect to user bus of user named like the calling user in container "foobar"
|
||||
*
|
||||
* Why? so that behaviour for "--machine=foobar --system" is roughly similar to
|
||||
* "--machine=foobar --user": both times we unconditionally connect as root user
|
||||
* regardless what the calling user is. */
|
||||
|
||||
rhs = machine;
|
||||
}
|
||||
|
||||
if (!isempty(rhs)) {
|
||||
erhs = bus_address_escape(rhs);
|
||||
if (!erhs)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* systemd-run -M… -PGq --wait -pUser=… -pPAMName=login systemd-stdio-bridge */
|
||||
|
||||
a = strjoin("unixexec:path=systemd-run,"
|
||||
"argv1=-M", erhs ?: ".host", ","
|
||||
"argv2=-PGq,"
|
||||
"argv3=--wait,"
|
||||
"argv4=-pUser%3d", eu ?: "root", ",",
|
||||
"argv5=-pPAMName%3dlogin,"
|
||||
"argv6=systemd-stdio-bridge");
|
||||
if (!a)
|
||||
return -ENOMEM;
|
||||
|
||||
if (user) {
|
||||
char *k;
|
||||
|
||||
/* Ideally we'd use the "--user" switch to systemd-stdio-bridge here, but it's only
|
||||
* available in recent systemd versions. Using the "-p" switch with the explicit path
|
||||
* is a working alternative, and is compatible with older versions, hence that's what
|
||||
* we use here. */
|
||||
|
||||
k = strjoin(a, ",argv7=-punix:path%3d%24%7bXDG_RUNTIME_DIR%7d/bus");
|
||||
if (!k)
|
||||
return -ENOMEM;
|
||||
|
||||
free_and_replace(a, k);
|
||||
}
|
||||
} else {
|
||||
_cleanup_free_ char *e = NULL;
|
||||
|
||||
/* Just a container name, we can go the simple way, and just join the container, and connect
|
||||
* to the well-known path of the system bus there. */
|
||||
|
||||
e = bus_address_escape(machine);
|
||||
if (!e)
|
||||
return -ENOMEM;
|
||||
@ -1528,30 +1606,137 @@ int bus_set_address_system_machine(sd_bus *b, const char *machine) {
|
||||
a = strjoin("x-machine-unix:machine=", e);
|
||||
if (!a)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return free_and_replace(b->address, a);
|
||||
}
|
||||
|
||||
_public_ int sd_bus_open_system_machine(sd_bus **ret, const char *machine) {
|
||||
static int user_and_machine_valid(const char *user_and_machine) {
|
||||
const char *h;
|
||||
|
||||
/* Checks if a container specification in the form "user@container" or just "container" is valid.
|
||||
*
|
||||
* If the "@" syntax is used we'll allow either the "user" or the "container" part to be omitted, but
|
||||
* not both. */
|
||||
|
||||
h = strchr(user_and_machine, '@');
|
||||
if (!h)
|
||||
h = user_and_machine;
|
||||
else {
|
||||
_cleanup_free_ char *user = NULL;
|
||||
|
||||
user = strndup(user_and_machine, h - user_and_machine);
|
||||
if (!user)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!isempty(user) && !valid_user_group_name(user, VALID_USER_RELAX))
|
||||
return false;
|
||||
|
||||
h++;
|
||||
|
||||
if (isempty(h))
|
||||
return !isempty(user);
|
||||
}
|
||||
|
||||
return hostname_is_valid(h, VALID_HOSTNAME_DOT_HOST);
|
||||
}
|
||||
|
||||
static int user_and_machine_equivalent(const char *user_and_machine) {
|
||||
_cleanup_free_ char *un = NULL;
|
||||
const char *f;
|
||||
|
||||
/* Returns true if the specified user+machine name are actually equivalent to our own identity and
|
||||
* our own host. If so we can shortcut things. Why bother? Because that way we don't have to fork
|
||||
* off short-lived worker processes that are then unavailable for authentication and logging in the
|
||||
* peer. Moreover joining a namespace requires privileges. If we are in the right namespace anyway,
|
||||
* we can avoid permission problems thus. */
|
||||
|
||||
assert(user_and_machine);
|
||||
|
||||
/* Omitting the user name means that we shall use the same user name as we run as locally, which
|
||||
* means we'll end up on the same host, let's shortcut */
|
||||
if (streq(user_and_machine, "@.host"))
|
||||
return true;
|
||||
|
||||
/* Otherwise, if we are root, then we can also allow the ".host" syntax, as that's the user this
|
||||
* would connect to. */
|
||||
if (geteuid() == 0 && STR_IN_SET(user_and_machine, ".host", "root@.host"))
|
||||
return true;
|
||||
|
||||
/* Otherwise, we have to figure our user name, and compare things with that. */
|
||||
un = getusername_malloc();
|
||||
if (!un)
|
||||
return -ENOMEM;
|
||||
|
||||
f = startswith(user_and_machine, un);
|
||||
if (!f)
|
||||
return false;
|
||||
|
||||
return STR_IN_SET(f, "@", "@.host");
|
||||
}
|
||||
|
||||
_public_ int sd_bus_open_system_machine(sd_bus **ret, const char *user_and_machine) {
|
||||
_cleanup_(bus_freep) sd_bus *b = NULL;
|
||||
int r;
|
||||
|
||||
assert_return(machine, -EINVAL);
|
||||
assert_return(user_and_machine, -EINVAL);
|
||||
assert_return(ret, -EINVAL);
|
||||
assert_return(streq(machine, ".host") || machine_name_is_valid(machine), -EINVAL);
|
||||
|
||||
if (user_and_machine_equivalent(user_and_machine))
|
||||
return sd_bus_open_system(ret);
|
||||
|
||||
r = user_and_machine_valid(user_and_machine);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
assert_return(r > 0, -EINVAL);
|
||||
|
||||
r = sd_bus_new(&b);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = bus_set_address_system_machine(b, machine);
|
||||
r = bus_set_address_machine(b, false, user_and_machine);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
b->bus_client = true;
|
||||
b->trusted = false;
|
||||
b->is_system = true;
|
||||
b->is_local = false;
|
||||
|
||||
r = sd_bus_start(b);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(b);
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_bus_open_user_machine(sd_bus **ret, const char *user_and_machine) {
|
||||
_cleanup_(bus_freep) sd_bus *b = NULL;
|
||||
int r;
|
||||
|
||||
assert_return(user_and_machine, -EINVAL);
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
/* Shortcut things if we'd end up on this host and as the same user. */
|
||||
if (user_and_machine_equivalent(user_and_machine))
|
||||
return sd_bus_open_user(ret);
|
||||
|
||||
r = user_and_machine_valid(user_and_machine);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
assert_return(r > 0, -EINVAL);
|
||||
|
||||
r = sd_bus_new(&b);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = bus_set_address_machine(b, true, user_and_machine);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
b->bus_client = true;
|
||||
b->trusted = true;
|
||||
|
||||
r = sd_bus_start(b);
|
||||
if (r < 0)
|
||||
|
||||
@ -847,7 +847,7 @@ _public_ int sd_get_machine_names(char ***machines) {
|
||||
|
||||
/* Filter out the unit: symlinks */
|
||||
for (a = b = l; *a; a++) {
|
||||
if (startswith(*a, "unit:") || !machine_name_is_valid(*a))
|
||||
if (startswith(*a, "unit:") || !hostname_is_valid(*a, 0))
|
||||
free(*a);
|
||||
else {
|
||||
*b = *a;
|
||||
@ -877,7 +877,7 @@ _public_ int sd_machine_get_class(const char *machine, char **class) {
|
||||
if (!c)
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
if (!machine_name_is_valid(machine))
|
||||
if (!hostname_is_valid(machine, 0))
|
||||
return -EINVAL;
|
||||
|
||||
p = strjoina("/run/systemd/machines/", machine);
|
||||
@ -899,7 +899,7 @@ _public_ int sd_machine_get_ifindices(const char *machine, int **ret_ifindices)
|
||||
const char *p;
|
||||
int r;
|
||||
|
||||
assert_return(machine_name_is_valid(machine), -EINVAL);
|
||||
assert_return(hostname_is_valid(machine, 0), -EINVAL);
|
||||
|
||||
p = strjoina("/run/systemd/machines/", machine);
|
||||
r = parse_env_file(NULL, p, "NETIF", &netif_line);
|
||||
|
||||
@ -487,7 +487,7 @@ static int container_bus_new(Machine *m, sd_bus_error *error, sd_bus **ret) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (asprintf(&address, "x-machine-kernel:pid=%1$" PID_PRI ";x-machine-unix:pid=%1$" PID_PRI, m->leader) < 0)
|
||||
if (asprintf(&address, "x-machine-unix:pid=%" PID_PRI, m->leader) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
bus->address = address;
|
||||
|
||||
@ -1561,7 +1561,7 @@ static int make_service_name(const char *name, char **ret) {
|
||||
assert(name);
|
||||
assert(ret);
|
||||
|
||||
if (!machine_name_is_valid(name))
|
||||
if (!hostname_is_valid(name, 0))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Invalid machine name %s.", name);
|
||||
|
||||
@ -1881,7 +1881,7 @@ static int import_tar(int argc, char *argv[], void *userdata) {
|
||||
|
||||
local = ll;
|
||||
|
||||
if (!machine_name_is_valid(local))
|
||||
if (!hostname_is_valid(local, 0))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Local name %s is not a suitable machine name.",
|
||||
local);
|
||||
@ -1941,7 +1941,7 @@ static int import_raw(int argc, char *argv[], void *userdata) {
|
||||
|
||||
local = ll;
|
||||
|
||||
if (!machine_name_is_valid(local))
|
||||
if (!hostname_is_valid(local, 0))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Local name %s is not a suitable machine name.",
|
||||
local);
|
||||
@ -1995,7 +1995,7 @@ static int import_fs(int argc, char *argv[], void *userdata) {
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Need either path or local name.");
|
||||
|
||||
if (!machine_name_is_valid(local))
|
||||
if (!hostname_is_valid(local, 0))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Local name %s is not a suitable machine name.",
|
||||
local);
|
||||
@ -2048,7 +2048,7 @@ static int export_tar(int argc, char *argv[], void *userdata) {
|
||||
assert(bus);
|
||||
|
||||
local = argv[1];
|
||||
if (!machine_name_is_valid(local))
|
||||
if (!hostname_is_valid(local, 0))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Machine name %s is not valid.", local);
|
||||
|
||||
@ -2090,7 +2090,7 @@ static int export_raw(int argc, char *argv[], void *userdata) {
|
||||
assert(bus);
|
||||
|
||||
local = argv[1];
|
||||
if (!machine_name_is_valid(local))
|
||||
if (!hostname_is_valid(local, 0))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Machine name %s is not valid.", local);
|
||||
|
||||
@ -2155,7 +2155,7 @@ static int pull_tar(int argc, char *argv[], void *userdata) {
|
||||
|
||||
local = ll;
|
||||
|
||||
if (!machine_name_is_valid(local))
|
||||
if (!hostname_is_valid(local, 0))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Local name %s is not a suitable machine name.",
|
||||
local);
|
||||
@ -2211,7 +2211,7 @@ static int pull_raw(int argc, char *argv[], void *userdata) {
|
||||
|
||||
local = ll;
|
||||
|
||||
if (!machine_name_is_valid(local))
|
||||
if (!hostname_is_valid(local, 0))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Local name %s is not a suitable machine name.",
|
||||
local);
|
||||
|
||||
@ -239,7 +239,7 @@ static int method_create_or_register_machine(Manager *manager, sd_bus_message *m
|
||||
r = sd_bus_message_read(message, "s", &name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (!machine_name_is_valid(name))
|
||||
if (!hostname_is_valid(name, 0))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine name");
|
||||
|
||||
r = sd_bus_message_read_array(message, 'y', &v, &n);
|
||||
|
||||
@ -166,7 +166,7 @@ static int manager_enumerate_machines(Manager *m) {
|
||||
if (startswith(de->d_name, "unit:"))
|
||||
continue;
|
||||
|
||||
if (!machine_name_is_valid(de->d_name))
|
||||
if (!hostname_is_valid(de->d_name, 0))
|
||||
continue;
|
||||
|
||||
k = manager_add_machine(m, de->d_name, &machine);
|
||||
|
||||
@ -601,7 +601,7 @@ static int parse_cmdline_ip_address(Context *context, int family, const char *va
|
||||
|
||||
if (p != value) {
|
||||
hostname = strndupa(value, p - value);
|
||||
if (!hostname_is_valid(hostname, false))
|
||||
if (!hostname_is_valid(hostname, 0))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
@ -1108,7 +1108,8 @@ static int link_set_flags(Link *link) {
|
||||
if (!link->network)
|
||||
return 0;
|
||||
|
||||
if (link->network->arp < 0 && link->network->multicast < 0 && link->network->allmulticast < 0)
|
||||
if (link->network->arp < 0 && link->network->multicast < 0 && link->network->allmulticast < 0 &&
|
||||
link->network->promiscuous < 0)
|
||||
return 0;
|
||||
|
||||
r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
|
||||
@ -1130,6 +1131,11 @@ static int link_set_flags(Link *link) {
|
||||
SET_FLAG(ifi_flags, IFF_ALLMULTI, link->network->allmulticast);
|
||||
}
|
||||
|
||||
if (link->network->promiscuous >= 0) {
|
||||
ifi_change |= IFF_PROMISC;
|
||||
SET_FLAG(ifi_flags, IFF_PROMISC, link->network->promiscuous);
|
||||
}
|
||||
|
||||
r = sd_rtnl_message_link_set_flags(req, ifi_flags, ifi_change);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not set link flags: %m");
|
||||
|
||||
@ -62,6 +62,7 @@ Link.Group, config_parse_uint32,
|
||||
Link.ARP, config_parse_tristate, 0, offsetof(Network, arp)
|
||||
Link.Multicast, config_parse_tristate, 0, offsetof(Network, multicast)
|
||||
Link.AllMulticast, config_parse_tristate, 0, offsetof(Network, allmulticast)
|
||||
Link.Promiscuous, config_parse_tristate, 0, offsetof(Network, promiscuous)
|
||||
Link.Unmanaged, config_parse_bool, 0, offsetof(Network, unmanaged)
|
||||
Link.RequiredForOnline, config_parse_required_for_online, 0, 0
|
||||
SR-IOV.VirtualFunction, config_parse_sr_iov_uint32, 0, 0
|
||||
|
||||
@ -321,6 +321,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
|
||||
.arp = -1,
|
||||
.multicast = -1,
|
||||
.allmulticast = -1,
|
||||
.promiscuous = -1,
|
||||
|
||||
.configure_without_carrier = false,
|
||||
.ignore_carrier_loss = -1,
|
||||
@ -922,7 +923,7 @@ int config_parse_hostname(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!hostname_is_valid(hn, false)) {
|
||||
if (!hostname_is_valid(hn, 0)) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"Hostname is not valid, ignoring assignment: %s", rvalue);
|
||||
return 0;
|
||||
|
||||
@ -87,6 +87,7 @@ struct Network {
|
||||
int arp;
|
||||
int multicast;
|
||||
int allmulticast;
|
||||
int promiscuous;
|
||||
bool unmanaged;
|
||||
bool required_for_online; /* Is this network required to be considered online? */
|
||||
LinkOperationalStateRange required_operstate_for_online;
|
||||
|
||||
@ -462,7 +462,7 @@ static int oci_hostname(const char *name, JsonVariant *v, JsonDispatchFlags flag
|
||||
|
||||
assert_se(n = json_variant_string(v));
|
||||
|
||||
if (!hostname_is_valid(n, false))
|
||||
if (!hostname_is_valid(n, 0))
|
||||
return json_log(v, flags, SYNTHETIC_ERRNO(EINVAL),
|
||||
"Hostname string is not a valid hostname: %s", n);
|
||||
|
||||
|
||||
@ -701,7 +701,7 @@ int config_parse_hostname(
|
||||
assert(rvalue);
|
||||
assert(s);
|
||||
|
||||
if (!hostname_is_valid(rvalue, false)) {
|
||||
if (!hostname_is_valid(rvalue, 0)) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid hostname, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -985,7 +985,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
if (isempty(optarg))
|
||||
arg_machine = mfree(arg_machine);
|
||||
else {
|
||||
if (!machine_name_is_valid(optarg))
|
||||
if (!hostname_is_valid(optarg, 0))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Invalid machine name: %s", optarg);
|
||||
|
||||
@ -999,7 +999,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
if (isempty(optarg))
|
||||
arg_hostname = mfree(arg_hostname);
|
||||
else {
|
||||
if (!hostname_is_valid(optarg, false))
|
||||
if (!hostname_is_valid(optarg, 0))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Invalid hostname: %s", optarg);
|
||||
|
||||
@ -2984,7 +2984,7 @@ static int determine_names(void) {
|
||||
return log_oom();
|
||||
|
||||
hostname_cleanup(arg_machine);
|
||||
if (!machine_name_is_valid(arg_machine))
|
||||
if (!hostname_is_valid(arg_machine, 0))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to determine machine name automatically, please use -M.");
|
||||
|
||||
if (arg_ephemeral) {
|
||||
|
||||
@ -249,7 +249,12 @@ int bus_connect_user_systemd(sd_bus **_bus) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **ret) {
|
||||
int bus_connect_transport(
|
||||
BusTransport transport,
|
||||
const char *host,
|
||||
bool user,
|
||||
sd_bus **ret) {
|
||||
|
||||
_cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
|
||||
int r;
|
||||
|
||||
@ -258,7 +263,7 @@ int bus_connect_transport(BusTransport transport, const char *host, bool user, s
|
||||
assert(ret);
|
||||
|
||||
assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
|
||||
assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
|
||||
assert_return(transport != BUS_TRANSPORT_REMOTE || !user, -EOPNOTSUPP);
|
||||
|
||||
switch (transport) {
|
||||
|
||||
@ -279,6 +284,9 @@ int bus_connect_transport(BusTransport transport, const char *host, bool user, s
|
||||
break;
|
||||
|
||||
case BUS_TRANSPORT_MACHINE:
|
||||
if (user)
|
||||
r = sd_bus_open_user_machine(&bus, host);
|
||||
else
|
||||
r = sd_bus_open_system_machine(&bus, host);
|
||||
break;
|
||||
|
||||
@ -293,7 +301,6 @@ int bus_connect_transport(BusTransport transport, const char *host, bool user, s
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(bus);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
#include "sd-bus.h"
|
||||
#include "sd-event.h"
|
||||
|
||||
#include "errno-util.h"
|
||||
#include "macro.h"
|
||||
#include "string-util.h"
|
||||
#include "time-util.h"
|
||||
@ -39,13 +40,21 @@ int bus_connect_transport(BusTransport transport, const char *host, bool user, s
|
||||
int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus);
|
||||
|
||||
#define bus_log_address_error(r) \
|
||||
log_error_errno(r, \
|
||||
r == -ENOMEDIUM ? "Failed to set bus address: $DBUS_SESSION_BUS_ADDRESS and $XDG_RUNTIME_DIR not defined" : \
|
||||
"Failed to set bus address: %m")
|
||||
({ \
|
||||
int _k = (r); \
|
||||
log_error_errno(_k, \
|
||||
_k == -ENOMEDIUM ? "Failed to set bus address: $DBUS_SESSION_BUS_ADDRESS and $XDG_RUNTIME_DIR not defined (consider using --machine=<user>@.host --user to connect to bus of other user)" : \
|
||||
"Failed to set bus address: %m"); \
|
||||
})
|
||||
|
||||
#define bus_log_connect_error(r) \
|
||||
log_error_errno(r, \
|
||||
r == -ENOMEDIUM ? "Failed to connect to bus: $DBUS_SESSION_BUS_ADDRESS and $XDG_RUNTIME_DIR not defined" : \
|
||||
"Failed to connect to bus: %m")
|
||||
({ \
|
||||
int _k = (r); \
|
||||
log_error_errno(_k, \
|
||||
_k == -ENOMEDIUM ? "Failed to connect to bus: $DBUS_SESSION_BUS_ADDRESS and $XDG_RUNTIME_DIR not defined (consider using --machine=<user>@.host --user to connect to bus of other user)" : \
|
||||
ERRNO_IS_PRIVILEGE(_k) ? "Failed to connect to bus: Operation not permitted (consider using --machine=<user>@.host --user to connect to bus of other user)" : \
|
||||
"Failed to connect to bus: %m"); \
|
||||
})
|
||||
|
||||
#define bus_log_parse_error(r) \
|
||||
log_error_errno(r, "Failed to parse bus message: %m")
|
||||
|
||||
@ -1523,9 +1523,6 @@ static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) {
|
||||
assert(machine);
|
||||
assert(boot_id);
|
||||
|
||||
if (!machine_name_is_valid(machine))
|
||||
return -EINVAL;
|
||||
|
||||
r = container_get_leader(machine, &pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
|
||||
static const char *arg_bus_path = DEFAULT_BUS_PATH;
|
||||
static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
|
||||
static bool arg_user = false;
|
||||
|
||||
static int help(void) {
|
||||
|
||||
@ -30,8 +31,10 @@ static int help(void) {
|
||||
"STDIO or socket-activatable proxy to a given DBus endpoint.\n\n"
|
||||
" -h --help Show this help\n"
|
||||
" --version Show package version\n"
|
||||
" -p --bus-path=PATH Path to the kernel bus (default: %s)\n"
|
||||
" -M --machine=MACHINE Name of machine to connect to\n",
|
||||
" -p --bus-path=PATH Path to the bus address (default: %s)\n"
|
||||
" --system Connect to system bus\n"
|
||||
" --user Connect to user bus\n"
|
||||
" -M --machine=CONTAINER Name of local container to connect to\n",
|
||||
program_invocation_short_name, DEFAULT_BUS_PATH);
|
||||
|
||||
return 0;
|
||||
@ -42,12 +45,16 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
enum {
|
||||
ARG_VERSION = 0x100,
|
||||
ARG_MACHINE,
|
||||
ARG_USER,
|
||||
ARG_SYSTEM,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, ARG_VERSION },
|
||||
{ "bus-path", required_argument, NULL, 'p' },
|
||||
{ "user", no_argument, NULL, ARG_USER },
|
||||
{ "system", no_argument, NULL, ARG_SYSTEM },
|
||||
{ "machine", required_argument, NULL, 'M' },
|
||||
{},
|
||||
};
|
||||
@ -67,6 +74,14 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
case ARG_VERSION:
|
||||
return version();
|
||||
|
||||
case ARG_USER:
|
||||
arg_user = true;
|
||||
break;
|
||||
|
||||
case ARG_SYSTEM:
|
||||
arg_user = false;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
arg_bus_path = optarg;
|
||||
break;
|
||||
@ -121,7 +136,7 @@ static int run(int argc, char *argv[]) {
|
||||
return log_error_errno(r, "Failed to allocate bus: %m");
|
||||
|
||||
if (arg_transport == BUS_TRANSPORT_MACHINE)
|
||||
r = bus_set_address_system_machine(a, arg_bus_path);
|
||||
r = bus_set_address_machine(a, arg_user, arg_bus_path);
|
||||
else
|
||||
r = sd_bus_set_address(a, arg_bus_path);
|
||||
if (r < 0)
|
||||
|
||||
@ -877,7 +877,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
||||
assert_not_reached("Unhandled option");
|
||||
}
|
||||
|
||||
if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM)
|
||||
if (arg_transport == BUS_TRANSPORT_REMOTE && arg_scope != UNIT_FILE_SYSTEM)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Cannot access user instance remotely.");
|
||||
|
||||
|
||||
@ -135,6 +135,7 @@ int sd_bus_open(sd_bus **ret);
|
||||
int sd_bus_open_with_description(sd_bus **ret, const char *description);
|
||||
int sd_bus_open_user(sd_bus **ret);
|
||||
int sd_bus_open_user_with_description(sd_bus **ret, const char *description);
|
||||
int sd_bus_open_user_machine(sd_bus **ret, const char *machine);
|
||||
int sd_bus_open_system(sd_bus **ret);
|
||||
int sd_bus_open_system_with_description(sd_bus **ret, const char *description);
|
||||
int sd_bus_open_system_remote(sd_bus **ret, const char *host);
|
||||
|
||||
@ -10,40 +10,40 @@
|
||||
#include "util.h"
|
||||
|
||||
static void test_hostname_is_valid(void) {
|
||||
assert_se(hostname_is_valid("foobar", false));
|
||||
assert_se(hostname_is_valid("foobar.com", false));
|
||||
assert_se(!hostname_is_valid("foobar.com.", false));
|
||||
assert_se(hostname_is_valid("fooBAR", false));
|
||||
assert_se(hostname_is_valid("fooBAR.com", false));
|
||||
assert_se(!hostname_is_valid("fooBAR.", false));
|
||||
assert_se(!hostname_is_valid("fooBAR.com.", false));
|
||||
assert_se(!hostname_is_valid("fööbar", false));
|
||||
assert_se(!hostname_is_valid("", false));
|
||||
assert_se(!hostname_is_valid(".", false));
|
||||
assert_se(!hostname_is_valid("..", false));
|
||||
assert_se(!hostname_is_valid("foobar.", false));
|
||||
assert_se(!hostname_is_valid(".foobar", false));
|
||||
assert_se(!hostname_is_valid("foo..bar", false));
|
||||
assert_se(!hostname_is_valid("foo.bar..", false));
|
||||
assert_se(!hostname_is_valid("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", false));
|
||||
assert_se(!hostname_is_valid("au-xph5-rvgrdsb5hcxc-47et3a5vvkrc-server-wyoz4elpdpe3.openstack.local", false));
|
||||
assert_se(hostname_is_valid("foobar", 0));
|
||||
assert_se(hostname_is_valid("foobar.com", 0));
|
||||
assert_se(!hostname_is_valid("foobar.com.", 0));
|
||||
assert_se(hostname_is_valid("fooBAR", 0));
|
||||
assert_se(hostname_is_valid("fooBAR.com", 0));
|
||||
assert_se(!hostname_is_valid("fooBAR.", 0));
|
||||
assert_se(!hostname_is_valid("fooBAR.com.", 0));
|
||||
assert_se(!hostname_is_valid("fööbar", 0));
|
||||
assert_se(!hostname_is_valid("", 0));
|
||||
assert_se(!hostname_is_valid(".", 0));
|
||||
assert_se(!hostname_is_valid("..", 0));
|
||||
assert_se(!hostname_is_valid("foobar.", 0));
|
||||
assert_se(!hostname_is_valid(".foobar", 0));
|
||||
assert_se(!hostname_is_valid("foo..bar", 0));
|
||||
assert_se(!hostname_is_valid("foo.bar..", 0));
|
||||
assert_se(!hostname_is_valid("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 0));
|
||||
assert_se(!hostname_is_valid("au-xph5-rvgrdsb5hcxc-47et3a5vvkrc-server-wyoz4elpdpe3.openstack.local", 0));
|
||||
|
||||
assert_se(hostname_is_valid("foobar", true));
|
||||
assert_se(hostname_is_valid("foobar.com", true));
|
||||
assert_se(hostname_is_valid("foobar.com.", true));
|
||||
assert_se(hostname_is_valid("fooBAR", true));
|
||||
assert_se(hostname_is_valid("fooBAR.com", true));
|
||||
assert_se(!hostname_is_valid("fooBAR.", true));
|
||||
assert_se(hostname_is_valid("fooBAR.com.", true));
|
||||
assert_se(!hostname_is_valid("fööbar", true));
|
||||
assert_se(!hostname_is_valid("", true));
|
||||
assert_se(!hostname_is_valid(".", true));
|
||||
assert_se(!hostname_is_valid("..", true));
|
||||
assert_se(!hostname_is_valid("foobar.", true));
|
||||
assert_se(!hostname_is_valid(".foobar", true));
|
||||
assert_se(!hostname_is_valid("foo..bar", true));
|
||||
assert_se(!hostname_is_valid("foo.bar..", true));
|
||||
assert_se(!hostname_is_valid("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", true));
|
||||
assert_se(hostname_is_valid("foobar", VALID_HOSTNAME_TRAILING_DOT));
|
||||
assert_se(hostname_is_valid("foobar.com", VALID_HOSTNAME_TRAILING_DOT));
|
||||
assert_se(hostname_is_valid("foobar.com.", VALID_HOSTNAME_TRAILING_DOT));
|
||||
assert_se(hostname_is_valid("fooBAR", VALID_HOSTNAME_TRAILING_DOT));
|
||||
assert_se(hostname_is_valid("fooBAR.com", VALID_HOSTNAME_TRAILING_DOT));
|
||||
assert_se(!hostname_is_valid("fooBAR.", VALID_HOSTNAME_TRAILING_DOT));
|
||||
assert_se(hostname_is_valid("fooBAR.com.", VALID_HOSTNAME_TRAILING_DOT));
|
||||
assert_se(!hostname_is_valid("fööbar", VALID_HOSTNAME_TRAILING_DOT));
|
||||
assert_se(!hostname_is_valid("", VALID_HOSTNAME_TRAILING_DOT));
|
||||
assert_se(!hostname_is_valid(".", VALID_HOSTNAME_TRAILING_DOT));
|
||||
assert_se(!hostname_is_valid("..", VALID_HOSTNAME_TRAILING_DOT));
|
||||
assert_se(!hostname_is_valid("foobar.", VALID_HOSTNAME_TRAILING_DOT));
|
||||
assert_se(!hostname_is_valid(".foobar", VALID_HOSTNAME_TRAILING_DOT));
|
||||
assert_se(!hostname_is_valid("foo..bar", VALID_HOSTNAME_TRAILING_DOT));
|
||||
assert_se(!hostname_is_valid("foo.bar..", VALID_HOSTNAME_TRAILING_DOT));
|
||||
assert_se(!hostname_is_valid("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", VALID_HOSTNAME_TRAILING_DOT));
|
||||
}
|
||||
|
||||
static void test_hostname_cleanup(void) {
|
||||
@ -151,7 +151,7 @@ static void test_hostname_malloc(void) {
|
||||
}
|
||||
|
||||
static void test_fallback_hostname(void) {
|
||||
if (!hostname_is_valid(FALLBACK_HOSTNAME, false)) {
|
||||
if (!hostname_is_valid(FALLBACK_HOSTNAME, 0)) {
|
||||
log_error("Configured fallback hostname \"%s\" is not valid.", FALLBACK_HOSTNAME);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
@ -3,7 +3,11 @@ set -e
|
||||
|
||||
TEST_DESCRIPTION="test MUMAPolicy= and NUMAMask= options"
|
||||
TEST_NO_NSPAWN=1
|
||||
QEMU_OPTIONS="-numa node,nodeid=0"
|
||||
. $TEST_BASE_DIR/test-functions
|
||||
if qemu_min_version "5.2.0"; then
|
||||
QEMU_OPTIONS="-object memory-backend-ram,id=mem0,size=512M -numa node,memdev=mem0,nodeid=0"
|
||||
else
|
||||
QEMU_OPTIONS="-numa node,nodeid=0"
|
||||
fi
|
||||
|
||||
do_test "$@" 36
|
||||
|
||||
@ -38,6 +38,7 @@ MTUBytes=
|
||||
Multicast=
|
||||
MACAddress=
|
||||
Group=
|
||||
Promiscuous=
|
||||
[SR-IOV]
|
||||
VirtualFunction=
|
||||
MACSpoofCheck=
|
||||
|
||||
@ -227,6 +227,24 @@ function find_qemu_bin() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Compares argument #1=X.Y.Z (X&Y&Z = numeric) to the version of the installed qemu
|
||||
# returns 0 if newer or equal
|
||||
# returns 1 if older
|
||||
# returns 2 if failing
|
||||
function qemu_min_version() {
|
||||
find_qemu_bin || return 2
|
||||
|
||||
# get version from binary
|
||||
qemu_ver=$($QEMU_BIN --version | awk '/^QEMU emulator version ([0-9]*\.[0-9]*\.[0-9]*) / {print $4}')
|
||||
|
||||
# Check version string format
|
||||
echo "$qemu_ver" | grep -q '^[0-9]*\.[0-9]*\.[0-9]*$' || return 2
|
||||
echo "$1" | grep -q '^[0-9]*\.[0-9]*\.[0-9]*$' || return 2
|
||||
|
||||
# compare as last command to return that value
|
||||
printf "%s\n%s\n" "$1" "$qemu_ver" | sort -V -C
|
||||
}
|
||||
|
||||
# Return 0 if QEMU did run (then you must check the result state/logs for actual
|
||||
# success), or 1 if QEMU is not available.
|
||||
run_qemu() {
|
||||
|
||||
@ -4104,7 +4104,9 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
|
||||
copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
|
||||
'dhcp-client-with-ipv4ll.network')
|
||||
start_networkd()
|
||||
self.wait_online(['veth99:degraded', 'veth-peer:routable'])
|
||||
# we need to increase timeout above default, as this will need to wait for
|
||||
# systemd-networkd to get the dhcpv4 transient failure event
|
||||
self.wait_online(['veth99:degraded', 'veth-peer:routable'], timeout='60s')
|
||||
|
||||
output = check_output('ip address show dev veth99')
|
||||
print(output)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user