2015-01-15 13:56:44 +01:00
|
|
|
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
|
|
|
|
|
|
|
/***
|
|
|
|
This file is part of systemd.
|
|
|
|
|
|
|
|
Copyright 2010 Lennart Poettering
|
|
|
|
Copyright 2013 Daniel Mack
|
|
|
|
Copyright 2014 Kay Sievers
|
|
|
|
|
|
|
|
systemd is free software; you can redistribute it and/or modify it
|
|
|
|
under the terms of the GNU Lesser General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2.1 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
systemd is distributed in the hope that it will be useful, but
|
|
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Lesser General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
|
|
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
***/
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stddef.h>
|
2015-10-24 22:58:24 +02:00
|
|
|
#include <string.h>
|
2015-01-15 13:56:44 +01:00
|
|
|
|
|
|
|
#include "sd-bus.h"
|
2015-10-24 22:58:24 +02:00
|
|
|
|
2015-10-27 03:01:06 +01:00
|
|
|
#include "alloc-util.h"
|
2015-01-15 13:56:44 +01:00
|
|
|
#include "bus-internal.h"
|
|
|
|
#include "bus-message.h"
|
|
|
|
#include "bus-util.h"
|
|
|
|
#include "driver.h"
|
2015-10-24 22:58:24 +02:00
|
|
|
#include "env-util.h"
|
2015-07-16 15:14:43 +02:00
|
|
|
#include "proxy.h"
|
2015-10-24 22:58:24 +02:00
|
|
|
#include "set.h"
|
|
|
|
#include "strv.h"
|
2015-01-15 13:56:44 +01:00
|
|
|
#include "synthesize.h"
|
2015-10-24 22:58:24 +02:00
|
|
|
#include "util.h"
|
2015-01-15 13:56:44 +01:00
|
|
|
|
|
|
|
static int get_creds_by_name(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
|
2015-01-15 13:56:44 +01:00
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(bus);
|
|
|
|
assert(name);
|
|
|
|
assert(_creds);
|
|
|
|
|
|
|
|
r = sd_bus_get_name_creds(bus, name, mask, &c);
|
|
|
|
if (r == -ESRCH || r == -ENXIO)
|
|
|
|
return sd_bus_error_setf(error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", name);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
*_creds = c;
|
|
|
|
c = NULL;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int get_creds_by_message(sd_bus *bus, sd_bus_message *m, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
|
|
|
|
const char *name;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(bus);
|
|
|
|
assert(m);
|
|
|
|
assert(_creds);
|
|
|
|
|
|
|
|
r = sd_bus_message_read(m, "s", &name);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
return get_creds_by_name(bus, name, mask, _creds, error);
|
|
|
|
}
|
|
|
|
|
bus-proxy: make StartServiceByName synchronous
The StartServiceByName() call was provided by dbus-daemon to activate a
service without sending a message. On receiption, dbus-daemon schedules
an activation request (different modes are supported) and sends back the
reply once activation is done.
With kdbus, we marked StartServiceByName() as deprecated. There is no
real reason to start services explicitly. Instead, applications should
just *use* the service and rely on it being activated implicitly.
However, we provide compatibility with dbus-daemon and implement
StartServiceByName() on the proxy via a call to
org.freedesktop.DBus.Peer.Ping() on the destination. This will activate
the peer implicitly as part of the no-op Ping() method call (regardless
whether the peer actually implements that call).
Now, the problem is, StartServiceByName() was synchronous on dbus-daemon
but isn't on bus-proxy. Hence, on return, there is no guarantee that
ListNames includes the activated name. As this is required by some
applications, we need to make this synchronous.
This patch makes the proxy track the Ping() method call and send the
reply of StartServiceByName() only once Ping() returned. We do not look
at possible errors of Ping(), as there is no strict requirement for the
peer to implement org.freedesktop.DBus.Peer. Furthermore, any interesting
error should have already been caught by sd_bus_send() before.
Note:
This race was triggered by gdbus. The gdbus-proxy implementation
relies on a name to be available after StartServiceByName()
returns. This is highly fragile and should be dropped by gdbus.
Even if the call is synchronous, there is no reason whatsoever to
assume the service did not exit-on-idle before ListNames()
returns.
However, this race is much less likely than the startup race, so
we try to be compatible to dbus-daemon now.
2015-07-31 13:25:04 +02:00
|
|
|
static int driver_activation(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
|
bus-proxy: make StartServiceByName synchronous
The StartServiceByName() call was provided by dbus-daemon to activate a
service without sending a message. On receiption, dbus-daemon schedules
an activation request (different modes are supported) and sends back the
reply once activation is done.
With kdbus, we marked StartServiceByName() as deprecated. There is no
real reason to start services explicitly. Instead, applications should
just *use* the service and rely on it being activated implicitly.
However, we provide compatibility with dbus-daemon and implement
StartServiceByName() on the proxy via a call to
org.freedesktop.DBus.Peer.Ping() on the destination. This will activate
the peer implicitly as part of the no-op Ping() method call (regardless
whether the peer actually implements that call).
Now, the problem is, StartServiceByName() was synchronous on dbus-daemon
but isn't on bus-proxy. Hence, on return, there is no guarantee that
ListNames includes the activated name. As this is required by some
applications, we need to make this synchronous.
This patch makes the proxy track the Ping() method call and send the
reply of StartServiceByName() only once Ping() returned. We do not look
at possible errors of Ping(), as there is no strict requirement for the
peer to implement org.freedesktop.DBus.Peer. Furthermore, any interesting
error should have already been caught by sd_bus_send() before.
Note:
This race was triggered by gdbus. The gdbus-proxy implementation
relies on a name to be available after StartServiceByName()
returns. This is highly fragile and should be dropped by gdbus.
Even if the call is synchronous, there is no reason whatsoever to
assume the service did not exit-on-idle before ListNames()
returns.
However, this race is much less likely than the startup race, so
we try to be compatible to dbus-daemon now.
2015-07-31 13:25:04 +02:00
|
|
|
ProxyActivation *activation = userdata;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The org.freedesktop.DBus.Peer.Ping() call returned. We don't care
|
|
|
|
* whether this succeeded, failed, was not implemented or timed out. We
|
|
|
|
* cannot assume that the target reacts to this properly. Hence, just
|
|
|
|
* send the reply to the activation request and be done.
|
|
|
|
*/
|
|
|
|
|
|
|
|
m = activation->request; /* claim reference */
|
|
|
|
|
|
|
|
--activation->proxy->n_activations;
|
|
|
|
LIST_REMOVE(activations_by_proxy, activation->proxy->activations, activation);
|
|
|
|
sd_bus_slot_unref(activation->slot);
|
|
|
|
free(activation);
|
|
|
|
|
|
|
|
return synthetic_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2015-07-16 15:14:43 +02:00
|
|
|
int bus_proxy_process_driver(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m, SharedPolicy *sp, const struct ucred *ucred, Set *owned_names) {
|
2015-01-15 13:56:44 +01:00
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(a);
|
|
|
|
assert(b);
|
|
|
|
assert(m);
|
|
|
|
|
|
|
|
if (!a->is_kernel)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!streq_ptr(sd_bus_message_get_destination(m), "org.freedesktop.DBus"))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* The "Hello()" call is is handled in process_hello() */
|
|
|
|
|
|
|
|
if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
|
|
|
|
|
|
|
|
if (!sd_bus_message_has_signature(m, ""))
|
|
|
|
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
|
|
|
|
|
|
|
|
return synthetic_reply_method_return(m, "s",
|
|
|
|
"<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" "
|
|
|
|
"\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
|
|
|
|
"<node>\n"
|
|
|
|
" <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
|
|
|
|
" <method name=\"Introspect\">\n"
|
|
|
|
" <arg name=\"data\" type=\"s\" direction=\"out\"/>\n"
|
|
|
|
" </method>\n"
|
|
|
|
" </interface>\n"
|
|
|
|
" <interface name=\"org.freedesktop.DBus\">\n"
|
|
|
|
" <method name=\"AddMatch\">\n"
|
|
|
|
" <arg type=\"s\" direction=\"in\"/>\n"
|
|
|
|
" </method>\n"
|
|
|
|
" <method name=\"RemoveMatch\">\n"
|
|
|
|
" <arg type=\"s\" direction=\"in\"/>\n"
|
|
|
|
" </method>\n"
|
2015-03-10 16:09:02 +01:00
|
|
|
" <method name=\"GetConnectionCredentials\">\n"
|
|
|
|
" <arg type=\"s\" direction=\"in\"/>\n"
|
|
|
|
" <arg type=\"a{sv}\" direction=\"out\"/>\n"
|
|
|
|
" </method>\n"
|
2015-01-15 13:56:44 +01:00
|
|
|
" <method name=\"GetConnectionSELinuxSecurityContext\">\n"
|
|
|
|
" <arg type=\"s\" direction=\"in\"/>\n"
|
|
|
|
" <arg type=\"ay\" direction=\"out\"/>\n"
|
|
|
|
" </method>\n"
|
|
|
|
" <method name=\"GetConnectionUnixProcessID\">\n"
|
|
|
|
" <arg type=\"s\" direction=\"in\"/>\n"
|
|
|
|
" <arg type=\"u\" direction=\"out\"/>\n"
|
|
|
|
" </method>\n"
|
|
|
|
" <method name=\"GetConnectionUnixUser\">\n"
|
|
|
|
" <arg type=\"s\" direction=\"in\"/>\n"
|
|
|
|
" <arg type=\"u\" direction=\"out\"/>\n"
|
|
|
|
" </method>\n"
|
|
|
|
" <method name=\"GetId\">\n"
|
|
|
|
" <arg type=\"s\" direction=\"out\"/>\n"
|
|
|
|
" </method>\n"
|
|
|
|
" <method name=\"GetNameOwner\">\n"
|
|
|
|
" <arg type=\"s\" direction=\"in\"/>\n"
|
|
|
|
" <arg type=\"s\" direction=\"out\"/>\n"
|
|
|
|
" </method>\n"
|
|
|
|
" <method name=\"Hello\">\n"
|
|
|
|
" <arg type=\"s\" direction=\"out\"/>\n"
|
|
|
|
" </method>\n"
|
|
|
|
" <method name=\"ListActivatableNames\">\n"
|
|
|
|
" <arg type=\"as\" direction=\"out\"/>\n"
|
|
|
|
" </method>\n"
|
|
|
|
" <method name=\"ListNames\">\n"
|
|
|
|
" <arg type=\"as\" direction=\"out\"/>\n"
|
|
|
|
" </method>\n"
|
|
|
|
" <method name=\"ListQueuedOwners\">\n"
|
|
|
|
" <arg type=\"s\" direction=\"in\"/>\n"
|
|
|
|
" <arg type=\"as\" direction=\"out\"/>\n"
|
|
|
|
" </method>\n"
|
|
|
|
" <method name=\"NameHasOwner\">\n"
|
|
|
|
" <arg type=\"s\" direction=\"in\"/>\n"
|
|
|
|
" <arg type=\"b\" direction=\"out\"/>\n"
|
|
|
|
" </method>\n"
|
|
|
|
" <method name=\"ReleaseName\">\n"
|
|
|
|
" <arg type=\"s\" direction=\"in\"/>\n"
|
|
|
|
" <arg type=\"u\" direction=\"out\"/>\n"
|
|
|
|
" </method>\n"
|
|
|
|
" <method name=\"ReloadConfig\">\n"
|
|
|
|
" </method>\n"
|
|
|
|
" <method name=\"RequestName\">\n"
|
|
|
|
" <arg type=\"s\" direction=\"in\"/>\n"
|
|
|
|
" <arg type=\"u\" direction=\"in\"/>\n"
|
|
|
|
" <arg type=\"u\" direction=\"out\"/>\n"
|
|
|
|
" </method>\n"
|
|
|
|
" <method name=\"StartServiceByName\">\n"
|
|
|
|
" <arg type=\"s\" direction=\"in\"/>\n"
|
|
|
|
" <arg type=\"u\" direction=\"in\"/>\n"
|
|
|
|
" <arg type=\"u\" direction=\"out\"/>\n"
|
|
|
|
" </method>\n"
|
|
|
|
" <method name=\"UpdateActivationEnvironment\">\n"
|
|
|
|
" <arg type=\"a{ss}\" direction=\"in\"/>\n"
|
|
|
|
" </method>\n"
|
|
|
|
" <signal name=\"NameAcquired\">\n"
|
|
|
|
" <arg type=\"s\"/>\n"
|
|
|
|
" </signal>\n"
|
|
|
|
" <signal name=\"NameLost\">\n"
|
|
|
|
" <arg type=\"s\"/>\n"
|
|
|
|
" </signal>\n"
|
|
|
|
" <signal name=\"NameOwnerChanged\">\n"
|
|
|
|
" <arg type=\"s\"/>\n"
|
|
|
|
" <arg type=\"s\"/>\n"
|
|
|
|
" <arg type=\"s\"/>\n"
|
|
|
|
" </signal>\n"
|
|
|
|
" </interface>\n"
|
|
|
|
"</node>\n");
|
|
|
|
|
|
|
|
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "AddMatch")) {
|
|
|
|
const char *match;
|
|
|
|
|
|
|
|
if (!sd_bus_message_has_signature(m, "s"))
|
|
|
|
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
|
|
|
|
|
|
|
|
r = sd_bus_message_read(m, "s", &match);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
2015-07-16 15:14:43 +02:00
|
|
|
r = sd_bus_add_match(a, NULL, match, proxy_match, p);
|
2015-01-15 13:56:44 +01:00
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
return synthetic_reply_method_return(m, NULL);
|
|
|
|
|
|
|
|
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RemoveMatch")) {
|
|
|
|
const char *match;
|
|
|
|
|
|
|
|
if (!sd_bus_message_has_signature(m, "s"))
|
|
|
|
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
|
|
|
|
|
|
|
|
r = sd_bus_message_read(m, "s", &match);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
r = bus_remove_match_by_string(a, match, NULL, NULL);
|
|
|
|
if (r == 0)
|
|
|
|
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule not found"));
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
return synthetic_reply_method_return(m, NULL);
|
|
|
|
|
2015-03-10 16:09:02 +01:00
|
|
|
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionCredentials")) {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
|
|
|
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
2015-03-10 16:09:02 +01:00
|
|
|
|
|
|
|
if (!sd_bus_message_has_signature(m, "s"))
|
|
|
|
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
|
|
|
|
|
|
|
|
r = get_creds_by_message(a, m, SD_BUS_CREDS_PID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SELINUX_CONTEXT, &creds, &error);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, &error);
|
|
|
|
|
|
|
|
r = sd_bus_message_new_method_return(m, &reply);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
r = sd_bus_message_open_container(reply, 'a', "{sv}");
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
/* Due to i.e. namespace translations some data might be missing */
|
|
|
|
|
|
|
|
if (creds->mask & SD_BUS_CREDS_PID) {
|
|
|
|
r = sd_bus_message_append(reply, "{sv}", "ProcessID", "u", (uint32_t) creds->pid);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (creds->mask & SD_BUS_CREDS_EUID) {
|
|
|
|
r = sd_bus_message_append(reply, "{sv}", "UnixUserID", "u", (uint32_t) creds->euid);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (creds->mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
|
|
|
|
r = sd_bus_message_open_container(reply, 'e', "sv");
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
r = sd_bus_message_append(reply, "s", "LinuxSecurityLabel");
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
r = sd_bus_message_open_container(reply, 'v', "ay");
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
r = sd_bus_message_append_array(reply, 'y', creds->label, strlen(creds->label));
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
r = sd_bus_message_close_container(reply);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
r = sd_bus_message_close_container(reply);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
r = sd_bus_message_close_container(reply);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
return synthetic_driver_send(m->bus, reply);
|
|
|
|
|
2015-01-15 13:56:44 +01:00
|
|
|
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionSELinuxSecurityContext")) {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
|
|
|
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
|
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
2015-01-15 13:56:44 +01:00
|
|
|
|
|
|
|
if (!sd_bus_message_has_signature(m, "s"))
|
|
|
|
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
|
|
|
|
|
|
|
|
r = get_creds_by_message(a, m, SD_BUS_CREDS_SELINUX_CONTEXT, &creds, &error);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, &error);
|
|
|
|
|
2015-03-10 16:09:02 +01:00
|
|
|
if (!(creds->mask & SD_BUS_CREDS_SELINUX_CONTEXT))
|
2015-03-13 14:08:00 +01:00
|
|
|
return synthetic_reply_method_errno(m, -EOPNOTSUPP, NULL);
|
2015-03-10 16:09:02 +01:00
|
|
|
|
2015-05-21 21:24:55 +02:00
|
|
|
r = sd_bus_message_new_method_return(m, &reply);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
r = sd_bus_message_append_array(reply, 'y', creds->label, strlen(creds->label));
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
return synthetic_driver_send(m->bus, reply);
|
2015-01-15 13:56:44 +01:00
|
|
|
|
|
|
|
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixProcessID")) {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
|
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
2015-01-15 13:56:44 +01:00
|
|
|
|
|
|
|
if (!sd_bus_message_has_signature(m, "s"))
|
|
|
|
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
|
|
|
|
|
|
|
|
r = get_creds_by_message(a, m, SD_BUS_CREDS_PID, &creds, &error);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, &error);
|
|
|
|
|
2015-03-10 16:09:02 +01:00
|
|
|
if (!(creds->mask & SD_BUS_CREDS_PID))
|
2015-03-13 14:08:00 +01:00
|
|
|
return synthetic_reply_method_errno(m, -EOPNOTSUPP, NULL);
|
2015-03-10 16:09:02 +01:00
|
|
|
|
2015-01-15 13:56:44 +01:00
|
|
|
return synthetic_reply_method_return(m, "u", (uint32_t) creds->pid);
|
|
|
|
|
|
|
|
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixUser")) {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
|
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
2015-01-15 13:56:44 +01:00
|
|
|
|
|
|
|
if (!sd_bus_message_has_signature(m, "s"))
|
|
|
|
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
|
|
|
|
|
bus: use EUID over UID and fix unix-creds
Whenever a process performs an action on an object, the kernel uses the
EUID of the process to do permission checks and to apply on any newly
created objects. The UID of a process is only used if someone *ELSE* acts
on the process. That is, the UID of a process defines who owns the
process, the EUID defines what privileges are used by this process when
performing an action.
Process limits, on the other hand, are always applied to the real UID, not
the effective UID. This is, because a process has a user object linked,
which always corresponds to its UID. A process never has a user object
linked for its EUID. Thus, accounting (and limits) is always done on the
real UID.
This commit fixes all sd-bus users to use the EUID when performing
privilege checks and alike. Furthermore, it fixes unix-creds to be parsed
as EUID, not UID (as the kernel always takes the EUID on UDS). Anyone
using UID (eg., to do user-accounting) has to fall back to the EUID as UDS
does not transmit the UID.
2015-01-18 13:55:55 +01:00
|
|
|
r = get_creds_by_message(a, m, SD_BUS_CREDS_EUID, &creds, &error);
|
2015-01-15 13:56:44 +01:00
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, &error);
|
|
|
|
|
2015-03-10 16:09:02 +01:00
|
|
|
if (!(creds->mask & SD_BUS_CREDS_EUID))
|
2015-03-13 14:08:00 +01:00
|
|
|
return synthetic_reply_method_errno(m, -EOPNOTSUPP, NULL);
|
2015-03-10 16:09:02 +01:00
|
|
|
|
2015-01-18 21:34:33 +01:00
|
|
|
return synthetic_reply_method_return(m, "u", (uint32_t) creds->euid);
|
2015-01-15 13:56:44 +01:00
|
|
|
|
|
|
|
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetId")) {
|
|
|
|
sd_id128_t server_id;
|
|
|
|
char buf[SD_ID128_STRING_MAX];
|
|
|
|
|
|
|
|
if (!sd_bus_message_has_signature(m, ""))
|
|
|
|
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
|
|
|
|
|
|
|
|
r = sd_bus_get_bus_id(a, &server_id);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
return synthetic_reply_method_return(m, "s", sd_id128_to_string(server_id, buf));
|
|
|
|
|
|
|
|
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetNameOwner")) {
|
|
|
|
const char *name;
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
|
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
2015-01-15 13:56:44 +01:00
|
|
|
|
|
|
|
if (!sd_bus_message_has_signature(m, "s"))
|
|
|
|
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
|
|
|
|
|
|
|
|
r = sd_bus_message_read(m, "s", &name);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
if (streq(name, "org.freedesktop.DBus"))
|
|
|
|
return synthetic_reply_method_return(m, "s", "org.freedesktop.DBus");
|
|
|
|
|
|
|
|
r = get_creds_by_name(a, name, SD_BUS_CREDS_UNIQUE_NAME, &creds, &error);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, &error);
|
|
|
|
|
2015-03-10 16:09:02 +01:00
|
|
|
if (!(creds->mask & SD_BUS_CREDS_UNIQUE_NAME))
|
2015-03-13 14:08:00 +01:00
|
|
|
return synthetic_reply_method_errno(m, -EOPNOTSUPP, NULL);
|
2015-03-10 16:09:02 +01:00
|
|
|
|
2015-01-15 13:56:44 +01:00
|
|
|
return synthetic_reply_method_return(m, "s", creds->unique_name);
|
|
|
|
|
|
|
|
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListActivatableNames")) {
|
|
|
|
_cleanup_strv_free_ char **names = NULL;
|
|
|
|
|
|
|
|
if (!sd_bus_message_has_signature(m, ""))
|
|
|
|
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
|
|
|
|
|
|
|
|
r = sd_bus_list_names(a, NULL, &names);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
/* Let's sort the names list to make it stable */
|
|
|
|
strv_sort(names);
|
|
|
|
|
2015-02-13 15:37:34 +01:00
|
|
|
return synthetic_reply_method_return_strv(m, names);
|
2015-01-15 13:56:44 +01:00
|
|
|
|
|
|
|
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListNames")) {
|
|
|
|
_cleanup_strv_free_ char **names = NULL;
|
|
|
|
|
|
|
|
if (!sd_bus_message_has_signature(m, ""))
|
|
|
|
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
|
|
|
|
|
|
|
|
r = sd_bus_list_names(a, &names, NULL);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
r = strv_extend(&names, "org.freedesktop.DBus");
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
/* Let's sort the names list to make it stable */
|
|
|
|
strv_sort(names);
|
|
|
|
|
2015-02-13 15:37:34 +01:00
|
|
|
return synthetic_reply_method_return_strv(m, names);
|
2015-01-15 13:56:44 +01:00
|
|
|
|
|
|
|
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListQueuedOwners")) {
|
2015-02-10 20:46:09 +01:00
|
|
|
struct kdbus_cmd_list cmd = {
|
|
|
|
.flags = KDBUS_LIST_QUEUED,
|
|
|
|
.size = sizeof(cmd),
|
|
|
|
};
|
2015-02-04 16:21:27 +01:00
|
|
|
struct kdbus_info *name_list, *name;
|
2015-01-15 13:56:44 +01:00
|
|
|
_cleanup_strv_free_ char **owners = NULL;
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
2015-01-15 13:56:44 +01:00
|
|
|
char *arg0;
|
|
|
|
int err = 0;
|
|
|
|
|
|
|
|
if (!sd_bus_message_has_signature(m, "s"))
|
|
|
|
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
|
|
|
|
|
|
|
|
r = sd_bus_message_read(m, "s", &arg0);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
r = sd_bus_get_name_creds(a, arg0, 0, NULL);
|
|
|
|
if (r == -ESRCH || r == -ENXIO) {
|
|
|
|
sd_bus_error_setf(&error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Could not get owners of name '%s': no such name.", arg0);
|
|
|
|
return synthetic_reply_method_errno(m, r, &error);
|
|
|
|
}
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
2015-02-04 16:21:27 +01:00
|
|
|
r = ioctl(a->input_fd, KDBUS_CMD_LIST, &cmd);
|
2015-01-15 13:56:44 +01:00
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, -errno, NULL);
|
|
|
|
|
2015-02-04 16:21:27 +01:00
|
|
|
name_list = (struct kdbus_info *) ((uint8_t *) a->kdbus_buffer + cmd.offset);
|
2015-01-15 13:56:44 +01:00
|
|
|
|
2015-02-04 16:21:27 +01:00
|
|
|
KDBUS_FOREACH(name, name_list, cmd.list_size) {
|
2015-01-15 13:56:44 +01:00
|
|
|
struct kdbus_item *item;
|
|
|
|
char *n;
|
|
|
|
|
2015-07-30 14:12:09 +02:00
|
|
|
KDBUS_ITEM_FOREACH(item, name, items) {
|
|
|
|
if (item->type == KDBUS_ITEM_OWNED_NAME) {
|
|
|
|
if (!streq_ptr(item->name.name, arg0))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (asprintf(&n, ":1.%llu", (unsigned long long) name->id) < 0) {
|
|
|
|
err = -ENOMEM;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = strv_consume(&owners, n);
|
|
|
|
if (r < 0) {
|
|
|
|
err = r;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2015-01-15 13:56:44 +01:00
|
|
|
}
|
|
|
|
|
2015-07-30 14:12:09 +02:00
|
|
|
if (err < 0)
|
2015-01-15 13:56:44 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = bus_kernel_cmd_free(a, cmd.offset);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
if (err < 0)
|
|
|
|
return synthetic_reply_method_errno(m, err, NULL);
|
|
|
|
|
2015-02-13 15:37:34 +01:00
|
|
|
return synthetic_reply_method_return_strv(m, owners);
|
2015-01-15 13:56:44 +01:00
|
|
|
|
|
|
|
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "NameHasOwner")) {
|
|
|
|
const char *name;
|
|
|
|
|
|
|
|
if (!sd_bus_message_has_signature(m, "s"))
|
|
|
|
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
|
|
|
|
|
|
|
|
r = sd_bus_message_read(m, "s", &name);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
if (streq(name, "org.freedesktop.DBus"))
|
|
|
|
return synthetic_reply_method_return(m, "b", true);
|
|
|
|
|
|
|
|
r = sd_bus_get_name_creds(a, name, 0, NULL);
|
|
|
|
if (r < 0 && r != -ESRCH && r != -ENXIO)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
return synthetic_reply_method_return(m, "b", r >= 0);
|
|
|
|
|
|
|
|
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReleaseName")) {
|
|
|
|
const char *name;
|
|
|
|
|
|
|
|
if (!sd_bus_message_has_signature(m, "s"))
|
|
|
|
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
|
|
|
|
|
|
|
|
r = sd_bus_message_read(m, "s", &name);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
r = sd_bus_release_name(a, name);
|
|
|
|
if (r < 0) {
|
|
|
|
if (r == -ESRCH)
|
|
|
|
return synthetic_reply_method_return(m, "u", BUS_NAME_NON_EXISTENT);
|
|
|
|
if (r == -EADDRINUSE)
|
|
|
|
return synthetic_reply_method_return(m, "u", BUS_NAME_NOT_OWNER);
|
|
|
|
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
set_remove(owned_names, (char*) name);
|
|
|
|
|
|
|
|
return synthetic_reply_method_return(m, "u", BUS_NAME_RELEASED);
|
|
|
|
|
|
|
|
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReloadConfig")) {
|
|
|
|
if (!sd_bus_message_has_signature(m, ""))
|
|
|
|
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
|
|
|
|
|
2015-01-17 19:06:34 +01:00
|
|
|
r = shared_policy_reload(sp);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
2015-01-15 13:56:44 +01:00
|
|
|
|
2015-01-17 19:06:34 +01:00
|
|
|
return synthetic_reply_method_return(m, NULL);
|
2015-01-15 13:56:44 +01:00
|
|
|
|
|
|
|
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RequestName")) {
|
|
|
|
const char *name;
|
|
|
|
uint32_t flags, param;
|
|
|
|
bool in_queue;
|
|
|
|
|
|
|
|
if (!sd_bus_message_has_signature(m, "su"))
|
|
|
|
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
|
|
|
|
|
|
|
|
r = sd_bus_message_read(m, "su", &name, &flags);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
2015-01-17 18:07:58 +01:00
|
|
|
if (sp) {
|
|
|
|
Policy *policy;
|
|
|
|
bool denied;
|
|
|
|
|
|
|
|
policy = shared_policy_acquire(sp);
|
|
|
|
denied = !policy_check_own(policy, ucred->uid, ucred->gid, name);
|
|
|
|
shared_policy_release(sp, policy);
|
|
|
|
if (denied)
|
|
|
|
return synthetic_reply_method_errno(m, -EPERM, NULL);
|
|
|
|
}
|
2015-01-15 13:56:44 +01:00
|
|
|
|
|
|
|
if ((flags & ~(BUS_NAME_ALLOW_REPLACEMENT|BUS_NAME_REPLACE_EXISTING|BUS_NAME_DO_NOT_QUEUE)) != 0)
|
|
|
|
return synthetic_reply_method_errno(m, -EINVAL, NULL);
|
|
|
|
|
|
|
|
param = 0;
|
|
|
|
if (flags & BUS_NAME_ALLOW_REPLACEMENT)
|
|
|
|
param |= SD_BUS_NAME_ALLOW_REPLACEMENT;
|
|
|
|
if (flags & BUS_NAME_REPLACE_EXISTING)
|
|
|
|
param |= SD_BUS_NAME_REPLACE_EXISTING;
|
|
|
|
if (!(flags & BUS_NAME_DO_NOT_QUEUE))
|
|
|
|
param |= SD_BUS_NAME_QUEUE;
|
|
|
|
|
|
|
|
r = set_put_strdup(owned_names, name);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
r = sd_bus_request_name(a, name, param);
|
|
|
|
if (r < 0) {
|
|
|
|
if (r == -EALREADY)
|
|
|
|
return synthetic_reply_method_return(m, "u", BUS_NAME_ALREADY_OWNER);
|
|
|
|
|
|
|
|
set_remove(owned_names, (char*) name);
|
|
|
|
|
|
|
|
if (r == -EEXIST)
|
|
|
|
return synthetic_reply_method_return(m, "u", BUS_NAME_EXISTS);
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
in_queue = (r == 0);
|
|
|
|
|
|
|
|
if (in_queue)
|
|
|
|
return synthetic_reply_method_return(m, "u", BUS_NAME_IN_QUEUE);
|
|
|
|
|
|
|
|
return synthetic_reply_method_return(m, "u", BUS_NAME_PRIMARY_OWNER);
|
|
|
|
|
|
|
|
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "StartServiceByName")) {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message *msg = NULL;
|
bus-proxy: make StartServiceByName synchronous
The StartServiceByName() call was provided by dbus-daemon to activate a
service without sending a message. On receiption, dbus-daemon schedules
an activation request (different modes are supported) and sends back the
reply once activation is done.
With kdbus, we marked StartServiceByName() as deprecated. There is no
real reason to start services explicitly. Instead, applications should
just *use* the service and rely on it being activated implicitly.
However, we provide compatibility with dbus-daemon and implement
StartServiceByName() on the proxy via a call to
org.freedesktop.DBus.Peer.Ping() on the destination. This will activate
the peer implicitly as part of the no-op Ping() method call (regardless
whether the peer actually implements that call).
Now, the problem is, StartServiceByName() was synchronous on dbus-daemon
but isn't on bus-proxy. Hence, on return, there is no guarantee that
ListNames includes the activated name. As this is required by some
applications, we need to make this synchronous.
This patch makes the proxy track the Ping() method call and send the
reply of StartServiceByName() only once Ping() returned. We do not look
at possible errors of Ping(), as there is no strict requirement for the
peer to implement org.freedesktop.DBus.Peer. Furthermore, any interesting
error should have already been caught by sd_bus_send() before.
Note:
This race was triggered by gdbus. The gdbus-proxy implementation
relies on a name to be available after StartServiceByName()
returns. This is highly fragile and should be dropped by gdbus.
Even if the call is synchronous, there is no reason whatsoever to
assume the service did not exit-on-idle before ListNames()
returns.
However, this race is much less likely than the startup race, so
we try to be compatible to dbus-daemon now.
2015-07-31 13:25:04 +02:00
|
|
|
ProxyActivation *activation;
|
2015-01-15 13:56:44 +01:00
|
|
|
const char *name;
|
2015-07-31 16:42:38 +02:00
|
|
|
uint64_t cookie;
|
2015-01-15 13:56:44 +01:00
|
|
|
uint32_t flags;
|
|
|
|
|
|
|
|
if (!sd_bus_message_has_signature(m, "su"))
|
|
|
|
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
|
|
|
|
|
|
|
|
r = sd_bus_message_read(m, "su", &name, &flags);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
if (flags != 0)
|
|
|
|
return synthetic_reply_method_errno(m, -EINVAL, NULL);
|
|
|
|
|
|
|
|
r = sd_bus_get_name_creds(a, name, 0, NULL);
|
|
|
|
if (r >= 0 || streq(name, "org.freedesktop.DBus"))
|
|
|
|
return synthetic_reply_method_return(m, "u", BUS_START_REPLY_ALREADY_RUNNING);
|
|
|
|
if (r != -ESRCH)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
bus-proxy: make StartServiceByName synchronous
The StartServiceByName() call was provided by dbus-daemon to activate a
service without sending a message. On receiption, dbus-daemon schedules
an activation request (different modes are supported) and sends back the
reply once activation is done.
With kdbus, we marked StartServiceByName() as deprecated. There is no
real reason to start services explicitly. Instead, applications should
just *use* the service and rely on it being activated implicitly.
However, we provide compatibility with dbus-daemon and implement
StartServiceByName() on the proxy via a call to
org.freedesktop.DBus.Peer.Ping() on the destination. This will activate
the peer implicitly as part of the no-op Ping() method call (regardless
whether the peer actually implements that call).
Now, the problem is, StartServiceByName() was synchronous on dbus-daemon
but isn't on bus-proxy. Hence, on return, there is no guarantee that
ListNames includes the activated name. As this is required by some
applications, we need to make this synchronous.
This patch makes the proxy track the Ping() method call and send the
reply of StartServiceByName() only once Ping() returned. We do not look
at possible errors of Ping(), as there is no strict requirement for the
peer to implement org.freedesktop.DBus.Peer. Furthermore, any interesting
error should have already been caught by sd_bus_send() before.
Note:
This race was triggered by gdbus. The gdbus-proxy implementation
relies on a name to be available after StartServiceByName()
returns. This is highly fragile and should be dropped by gdbus.
Even if the call is synchronous, there is no reason whatsoever to
assume the service did not exit-on-idle before ListNames()
returns.
However, this race is much less likely than the startup race, so
we try to be compatible to dbus-daemon now.
2015-07-31 13:25:04 +02:00
|
|
|
if (p->n_activations >= PROXY_ACTIVATIONS_MAX)
|
|
|
|
return synthetic_reply_method_errno(m, -EMFILE, NULL);
|
|
|
|
|
2015-07-31 16:42:38 +02:00
|
|
|
r = sd_bus_message_get_cookie(m, &cookie);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
r = sd_bus_message_new_method_call(a,
|
|
|
|
&msg,
|
|
|
|
name,
|
|
|
|
"/",
|
|
|
|
"org.freedesktop.DBus.Peer",
|
|
|
|
"Ping");
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
r = bus_message_seal(msg, cookie, BUS_DEFAULT_TIMEOUT);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
bus-proxy: make StartServiceByName synchronous
The StartServiceByName() call was provided by dbus-daemon to activate a
service without sending a message. On receiption, dbus-daemon schedules
an activation request (different modes are supported) and sends back the
reply once activation is done.
With kdbus, we marked StartServiceByName() as deprecated. There is no
real reason to start services explicitly. Instead, applications should
just *use* the service and rely on it being activated implicitly.
However, we provide compatibility with dbus-daemon and implement
StartServiceByName() on the proxy via a call to
org.freedesktop.DBus.Peer.Ping() on the destination. This will activate
the peer implicitly as part of the no-op Ping() method call (regardless
whether the peer actually implements that call).
Now, the problem is, StartServiceByName() was synchronous on dbus-daemon
but isn't on bus-proxy. Hence, on return, there is no guarantee that
ListNames includes the activated name. As this is required by some
applications, we need to make this synchronous.
This patch makes the proxy track the Ping() method call and send the
reply of StartServiceByName() only once Ping() returned. We do not look
at possible errors of Ping(), as there is no strict requirement for the
peer to implement org.freedesktop.DBus.Peer. Furthermore, any interesting
error should have already been caught by sd_bus_send() before.
Note:
This race was triggered by gdbus. The gdbus-proxy implementation
relies on a name to be available after StartServiceByName()
returns. This is highly fragile and should be dropped by gdbus.
Even if the call is synchronous, there is no reason whatsoever to
assume the service did not exit-on-idle before ListNames()
returns.
However, this race is much less likely than the startup race, so
we try to be compatible to dbus-daemon now.
2015-07-31 13:25:04 +02:00
|
|
|
activation = new0(ProxyActivation, 1);
|
|
|
|
if (!activation)
|
|
|
|
return synthetic_reply_method_errno(m, -ENOMEM, NULL);
|
|
|
|
|
2015-07-31 16:42:38 +02:00
|
|
|
r = sd_bus_call_async(a,
|
|
|
|
&activation->slot,
|
|
|
|
msg,
|
|
|
|
driver_activation,
|
|
|
|
activation,
|
|
|
|
0);
|
bus-proxy: make StartServiceByName synchronous
The StartServiceByName() call was provided by dbus-daemon to activate a
service without sending a message. On receiption, dbus-daemon schedules
an activation request (different modes are supported) and sends back the
reply once activation is done.
With kdbus, we marked StartServiceByName() as deprecated. There is no
real reason to start services explicitly. Instead, applications should
just *use* the service and rely on it being activated implicitly.
However, we provide compatibility with dbus-daemon and implement
StartServiceByName() on the proxy via a call to
org.freedesktop.DBus.Peer.Ping() on the destination. This will activate
the peer implicitly as part of the no-op Ping() method call (regardless
whether the peer actually implements that call).
Now, the problem is, StartServiceByName() was synchronous on dbus-daemon
but isn't on bus-proxy. Hence, on return, there is no guarantee that
ListNames includes the activated name. As this is required by some
applications, we need to make this synchronous.
This patch makes the proxy track the Ping() method call and send the
reply of StartServiceByName() only once Ping() returned. We do not look
at possible errors of Ping(), as there is no strict requirement for the
peer to implement org.freedesktop.DBus.Peer. Furthermore, any interesting
error should have already been caught by sd_bus_send() before.
Note:
This race was triggered by gdbus. The gdbus-proxy implementation
relies on a name to be available after StartServiceByName()
returns. This is highly fragile and should be dropped by gdbus.
Even if the call is synchronous, there is no reason whatsoever to
assume the service did not exit-on-idle before ListNames()
returns.
However, this race is much less likely than the startup race, so
we try to be compatible to dbus-daemon now.
2015-07-31 13:25:04 +02:00
|
|
|
if (r < 0) {
|
|
|
|
free(activation);
|
2015-01-15 13:56:44 +01:00
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
bus-proxy: make StartServiceByName synchronous
The StartServiceByName() call was provided by dbus-daemon to activate a
service without sending a message. On receiption, dbus-daemon schedules
an activation request (different modes are supported) and sends back the
reply once activation is done.
With kdbus, we marked StartServiceByName() as deprecated. There is no
real reason to start services explicitly. Instead, applications should
just *use* the service and rely on it being activated implicitly.
However, we provide compatibility with dbus-daemon and implement
StartServiceByName() on the proxy via a call to
org.freedesktop.DBus.Peer.Ping() on the destination. This will activate
the peer implicitly as part of the no-op Ping() method call (regardless
whether the peer actually implements that call).
Now, the problem is, StartServiceByName() was synchronous on dbus-daemon
but isn't on bus-proxy. Hence, on return, there is no guarantee that
ListNames includes the activated name. As this is required by some
applications, we need to make this synchronous.
This patch makes the proxy track the Ping() method call and send the
reply of StartServiceByName() only once Ping() returned. We do not look
at possible errors of Ping(), as there is no strict requirement for the
peer to implement org.freedesktop.DBus.Peer. Furthermore, any interesting
error should have already been caught by sd_bus_send() before.
Note:
This race was triggered by gdbus. The gdbus-proxy implementation
relies on a name to be available after StartServiceByName()
returns. This is highly fragile and should be dropped by gdbus.
Even if the call is synchronous, there is no reason whatsoever to
assume the service did not exit-on-idle before ListNames()
returns.
However, this race is much less likely than the startup race, so
we try to be compatible to dbus-daemon now.
2015-07-31 13:25:04 +02:00
|
|
|
}
|
2015-01-15 13:56:44 +01:00
|
|
|
|
bus-proxy: make StartServiceByName synchronous
The StartServiceByName() call was provided by dbus-daemon to activate a
service without sending a message. On receiption, dbus-daemon schedules
an activation request (different modes are supported) and sends back the
reply once activation is done.
With kdbus, we marked StartServiceByName() as deprecated. There is no
real reason to start services explicitly. Instead, applications should
just *use* the service and rely on it being activated implicitly.
However, we provide compatibility with dbus-daemon and implement
StartServiceByName() on the proxy via a call to
org.freedesktop.DBus.Peer.Ping() on the destination. This will activate
the peer implicitly as part of the no-op Ping() method call (regardless
whether the peer actually implements that call).
Now, the problem is, StartServiceByName() was synchronous on dbus-daemon
but isn't on bus-proxy. Hence, on return, there is no guarantee that
ListNames includes the activated name. As this is required by some
applications, we need to make this synchronous.
This patch makes the proxy track the Ping() method call and send the
reply of StartServiceByName() only once Ping() returned. We do not look
at possible errors of Ping(), as there is no strict requirement for the
peer to implement org.freedesktop.DBus.Peer. Furthermore, any interesting
error should have already been caught by sd_bus_send() before.
Note:
This race was triggered by gdbus. The gdbus-proxy implementation
relies on a name to be available after StartServiceByName()
returns. This is highly fragile and should be dropped by gdbus.
Even if the call is synchronous, there is no reason whatsoever to
assume the service did not exit-on-idle before ListNames()
returns.
However, this race is much less likely than the startup race, so
we try to be compatible to dbus-daemon now.
2015-07-31 13:25:04 +02:00
|
|
|
activation->proxy = p;
|
|
|
|
activation->request = sd_bus_message_ref(m);
|
|
|
|
LIST_PREPEND(activations_by_proxy, p->activations, activation);
|
|
|
|
++p->n_activations;
|
|
|
|
return 1;
|
2015-01-15 13:56:44 +01:00
|
|
|
|
|
|
|
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "UpdateActivationEnvironment")) {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message *msg = NULL;
|
2015-01-15 13:56:44 +01:00
|
|
|
_cleanup_strv_free_ char **args = NULL;
|
|
|
|
|
|
|
|
if (!sd_bus_message_has_signature(m, "a{ss}"))
|
|
|
|
return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
|
|
|
|
|
|
|
|
r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{ss}");
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "ss")) > 0) {
|
|
|
|
_cleanup_free_ char *s = NULL;
|
|
|
|
const char *key;
|
|
|
|
const char *value;
|
|
|
|
|
|
|
|
r = sd_bus_message_read(m, "ss", &key, &value);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
s = strjoin(key, "=", value, NULL);
|
|
|
|
if (!s)
|
|
|
|
return synthetic_reply_method_errno(m, -ENOMEM, NULL);
|
|
|
|
|
2015-08-04 13:36:03 +02:00
|
|
|
if (!env_assignment_is_valid(s)) {
|
|
|
|
log_warning("UpdateActivationEnvironment() called with invalid assignment, discarding: %s", s);
|
|
|
|
} else {
|
|
|
|
r = strv_extend(&args, s);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
}
|
2015-01-15 13:56:44 +01:00
|
|
|
|
|
|
|
r = sd_bus_message_exit_container(m);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
r = sd_bus_message_exit_container(m);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
2015-07-31 18:56:38 +02:00
|
|
|
if (strv_isempty(args)) /* nothing to do? */
|
|
|
|
return synthetic_reply_method_return(m, NULL);
|
2015-01-15 13:56:44 +01:00
|
|
|
|
|
|
|
r = sd_bus_message_new_method_call(
|
|
|
|
a,
|
|
|
|
&msg,
|
|
|
|
"org.freedesktop.systemd1",
|
|
|
|
"/org/freedesktop/systemd1",
|
|
|
|
"org.freedesktop.systemd1.Manager",
|
|
|
|
"SetEnvironment");
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
r = sd_bus_message_append_strv(msg, args);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
|
|
|
r = sd_bus_call(a, msg, 0, NULL, NULL);
|
|
|
|
if (r < 0)
|
|
|
|
return synthetic_reply_method_errno(m, r, NULL);
|
|
|
|
|
2015-01-17 18:54:09 +01:00
|
|
|
return synthetic_reply_method_return(m, NULL);
|
2015-01-15 13:56:44 +01:00
|
|
|
|
|
|
|
} else {
|
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
|
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
2015-01-15 13:56:44 +01:00
|
|
|
|
|
|
|
r = sd_bus_error_setf(&error, SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method '%s'.", m->member);
|
|
|
|
|
|
|
|
return synthetic_reply_method_errno(m, r, &error);
|
|
|
|
}
|
|
|
|
}
|