+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Set") && properties) {
+ const char *interface, *property;
+ DBusMessageIter iter;
+ const BusProperty *p;
+
+ if (!dbus_message_iter_init(message, &iter) ||
+ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+ return bus_send_error_reply(m, c, message, NULL, -EINVAL);
+
+ dbus_message_iter_get_basic(&iter, &interface);
+
+ if (!dbus_message_iter_next(&iter) ||
+ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+ return bus_send_error_reply(m, c, message, NULL, -EINVAL);
+
+ dbus_message_iter_get_basic(&iter, &property);
+
+ if (!dbus_message_iter_next(&iter) ||
+ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT ||
+ dbus_message_iter_has_next(&iter))
+ return bus_send_error_reply(m, c, message, NULL, -EINVAL);
+
+ for (p = properties; p->property; p++)
+ if (streq(p->interface, interface) && streq(p->property, property))
+ break;
+
+ if (p->set) {
+ DBusMessageIter sub;
+ char *sig;
+
+ dbus_message_iter_recurse(&iter, &sub);
+
+ if (!(sig = dbus_message_iter_get_signature(&sub)))
+ goto oom;
+
+ if (!streq(sig, p->signature)) {
+ dbus_free(sig);
+ return bus_send_error_reply(m, c, message, NULL, -EINVAL);
+ }
+
+ dbus_free(sig);
+
+ if ((r = p->set(m, &sub, property)) < 0) {
+ if (r == -ENOMEM)
+ goto oom;
+ return bus_send_error_reply(m, c, message, NULL, r);
+ }
+
+ if (!(reply = dbus_message_new_method_return(message)))
+ goto oom;
+ } else {
+ if (p->property)
+ dbus_set_error_const(&error, DBUS_ERROR_PROPERTY_READ_ONLY, "Property read-only");
+ else if (!nulstr_contains(interfaces, interface))
+ dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
+ else
+ dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_PROPERTY, "Unknown property");
+
+ return bus_send_error_reply(m, c, message, &error, -EINVAL);
+ }
+
+ } else if (!nulstr_contains(interfaces, dbus_message_get_interface(message))) {
+ dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
+ return bus_send_error_reply(m, c, message, &error, -EINVAL);